summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Souders <dsouders@vmware.com>2015-08-28 09:56:56 -0400
committerDouglas Souders <dsouders@vmware.com>2015-08-28 09:56:56 -0400
commitebed1074323950b03d25b31c54741eaa128c3e0c (patch)
treea20bff365419462d1a8a2894ed834e27713c3d9f
parent39228f1efb8b4070d1ca2636e4f552c106346f46 (diff)
release 10.0.0 from build 3000743
-rw-r--r--open-vm-tools/ChangeLog623
-rw-r--r--open-vm-tools/LICENSE406
-rw-r--r--open-vm-tools/Makefile.am1
-rw-r--r--open-vm-tools/Makefile.in4
-rw-r--r--open-vm-tools/NEWS25
-rw-r--r--open-vm-tools/autom4te.cache/output.038
-rw-r--r--open-vm-tools/autom4te.cache/output.138
-rw-r--r--open-vm-tools/autom4te.cache/output.238
-rw-r--r--open-vm-tools/autom4te.cache/traces.0320
-rw-r--r--open-vm-tools/autom4te.cache/traces.1657
-rw-r--r--open-vm-tools/autom4te.cache/traces.2320
-rwxr-xr-x[-rw-r--r--]open-vm-tools/configure38
-rw-r--r--open-vm-tools/configure.ac18
-rw-r--r--open-vm-tools/guestproxycerttool/cert_key.c8
-rw-r--r--open-vm-tools/guestproxycerttool/cert_key.h9
-rw-r--r--open-vm-tools/guestproxycerttool/cert_tool.c201
-rw-r--r--open-vm-tools/guestproxycerttool/cert_util.c71
-rw-r--r--open-vm-tools/guestproxycerttool/cert_util.h10
-rw-r--r--open-vm-tools/hgfsmounter/hgfsmounter.c72
-rw-r--r--open-vm-tools/lib/Makefile.am4
-rw-r--r--open-vm-tools/lib/Makefile.in18
-rw-r--r--open-vm-tools/lib/appUtil/appUtil.c4
-rw-r--r--open-vm-tools/lib/appUtil/appUtilX11.c2
-rw-r--r--open-vm-tools/lib/asyncsocket/asyncSocketInt.h83
-rw-r--r--open-vm-tools/lib/asyncsocket/asyncsocket.c197
-rw-r--r--open-vm-tools/lib/auth/authPosix.c8
-rw-r--r--open-vm-tools/lib/backdoor/backdoor.c45
-rw-r--r--open-vm-tools/lib/dict/dictll.c12
-rw-r--r--open-vm-tools/lib/dynxdr/xdrutil.c2
-rw-r--r--open-vm-tools/lib/err/errInt.h6
-rw-r--r--open-vm-tools/lib/file/file.c597
-rw-r--r--open-vm-tools/lib/file/fileIO.c77
-rw-r--r--open-vm-tools/lib/file/fileIOPosix.c384
-rw-r--r--open-vm-tools/lib/file/fileInt.h46
-rw-r--r--open-vm-tools/lib/file/fileLockPosix.c48
-rw-r--r--open-vm-tools/lib/file/fileLockPrimitive.c299
-rw-r--r--open-vm-tools/lib/file/filePosix.c465
-rw-r--r--open-vm-tools/lib/file/fileStandAlone.c130
-rw-r--r--open-vm-tools/lib/file/fileTemp.c63
-rw-r--r--open-vm-tools/lib/file/fileTempPosix.c23
-rw-r--r--open-vm-tools/lib/foundryMsg/foundryMsg.c35
-rw-r--r--open-vm-tools/lib/foundryMsg/vixTranslateErrOpenSource.c9
-rw-r--r--open-vm-tools/lib/glibUtils/fileLogger.c26
-rw-r--r--open-vm-tools/lib/guestRpc/nicinfo.x2
-rw-r--r--open-vm-tools/lib/hashMap/hashMap.c36
-rw-r--r--open-vm-tools/lib/hgfs/hgfsEscape.c9
-rw-r--r--open-vm-tools/lib/hgfsHelper/hgfsHelperPosix.c8
-rw-r--r--open-vm-tools/lib/hgfsServer/hgfsServer.c518
-rw-r--r--open-vm-tools/lib/hgfsServer/hgfsServerInt.h65
-rw-r--r--open-vm-tools/lib/hgfsServer/hgfsServerLinux.c593
-rw-r--r--open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c122
-rw-r--r--open-vm-tools/lib/hgfsServer/hgfsServerParameters.c100
-rw-r--r--open-vm-tools/lib/hgfsServer/hgfsServerParameters.h2
-rw-r--r--open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuest.c17
-rw-r--r--open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuestInt.h2
-rw-r--r--open-vm-tools/lib/hgfsServerManagerGuest/hgfsServerManagerGuest.c24
-rw-r--r--open-vm-tools/lib/hgfsServerPolicyGuest/hgfsServerPolicyGuest.c63
-rw-r--r--open-vm-tools/lib/hgfsUri/Makefile.am (renamed from open-vm-tools/lib/printer/Makefile.am)13
-rw-r--r--open-vm-tools/lib/hgfsUri/hgfsUriPosix.c110
-rw-r--r--open-vm-tools/lib/include/appUtil.h7
-rw-r--r--open-vm-tools/lib/include/asyncsocket.h55
-rw-r--r--open-vm-tools/lib/include/auth.h2
-rw-r--r--open-vm-tools/lib/include/backdoor_def.h42
-rw-r--r--open-vm-tools/lib/include/base64.h7
-rw-r--r--open-vm-tools/lib/include/bsdfmt.h2
-rw-r--r--open-vm-tools/lib/include/buildNumber.h12
-rw-r--r--open-vm-tools/lib/include/clamped.h75
-rw-r--r--open-vm-tools/lib/include/codeset.h36
-rw-r--r--open-vm-tools/lib/include/conf.h24
-rw-r--r--open-vm-tools/lib/include/dbllnklst.h20
-rw-r--r--open-vm-tools/lib/include/dictll.h2
-rw-r--r--open-vm-tools/lib/include/dynbuf.h22
-rw-r--r--open-vm-tools/lib/include/escape.h7
-rw-r--r--open-vm-tools/lib/include/file.h222
-rw-r--r--open-vm-tools/lib/include/fileIO.h79
-rw-r--r--open-vm-tools/lib/include/fileLock.h10
-rw-r--r--open-vm-tools/lib/include/file_extensions.h8
-rw-r--r--open-vm-tools/lib/include/ghIntegrationCommon.h34
-rw-r--r--open-vm-tools/lib/include/guestInfo.h3
-rw-r--r--open-vm-tools/lib/include/guestStats.h271
-rw-r--r--open-vm-tools/lib/include/guest_os.h19
-rw-r--r--open-vm-tools/lib/include/guest_os_tables.h143
-rw-r--r--open-vm-tools/lib/include/hashTable.h82
-rw-r--r--open-vm-tools/lib/include/hgfsDevLinux.h26
-rw-r--r--open-vm-tools/lib/include/hgfsEscape.h16
-rw-r--r--open-vm-tools/lib/include/hgfsHelper.h6
-rw-r--r--open-vm-tools/lib/include/hgfsProto.h19
-rw-r--r--open-vm-tools/lib/include/hgfsServer.h109
-rw-r--r--open-vm-tools/lib/include/hgfsServerPolicy.h39
-rw-r--r--open-vm-tools/lib/include/hgfsTransport.h7
-rw-r--r--open-vm-tools/lib/include/hgfsUri.h (renamed from open-vm-tools/lib/include/printer.h)27
-rw-r--r--open-vm-tools/lib/include/hostType.h7
-rw-r--r--open-vm-tools/lib/include/hostinfo.h8
-rw-r--r--open-vm-tools/lib/include/iovector.h12
-rw-r--r--open-vm-tools/lib/include/log.h119
-rw-r--r--open-vm-tools/lib/include/loglevel_user.h25
-rw-r--r--open-vm-tools/lib/include/message.h37
-rw-r--r--open-vm-tools/lib/include/msg.h2
-rw-r--r--open-vm-tools/lib/include/msgid.h2
-rw-r--r--open-vm-tools/lib/include/msgid_defs.h (renamed from open-vm-tools/lib/include/msgidDefs.h)2
-rw-r--r--open-vm-tools/lib/include/mutexRankLib.h49
-rw-r--r--open-vm-tools/lib/include/netutil.h2
-rw-r--r--open-vm-tools/lib/include/poll.h2
-rw-r--r--open-vm-tools/lib/include/posix.h192
-rw-r--r--open-vm-tools/lib/include/productState.h7
-rw-r--r--open-vm-tools/lib/include/rpcout.h18
-rw-r--r--open-vm-tools/lib/include/sha1.h28
-rw-r--r--open-vm-tools/lib/include/sigPosixRegs.h4
-rw-r--r--open-vm-tools/lib/include/sslDirect.h2
-rw-r--r--open-vm-tools/lib/include/str.h133
-rw-r--r--open-vm-tools/lib/include/system.h2
-rw-r--r--open-vm-tools/lib/include/unicodeBase.h83
-rw-r--r--open-vm-tools/lib/include/unicodeICU.h12
-rw-r--r--open-vm-tools/lib/include/unicodeOperations.h158
-rw-r--r--open-vm-tools/lib/include/unicodeTransforms.h8
-rw-r--r--open-vm-tools/lib/include/unicodeTypes.h25
-rw-r--r--open-vm-tools/lib/include/userlock.h93
-rw-r--r--open-vm-tools/lib/include/util.h69
-rw-r--r--open-vm-tools/lib/include/util_shared.h32
-rw-r--r--open-vm-tools/lib/include/uuid.h99
-rw-r--r--open-vm-tools/lib/include/vix.h37
-rw-r--r--open-vm-tools/lib/include/vixCommands.h83
-rw-r--r--open-vm-tools/lib/include/vm_assert.h13
-rw-r--r--open-vm-tools/lib/include/vm_atomic.h1520
-rw-r--r--open-vm-tools/lib/include/vm_basic_asm.h536
-rw-r--r--open-vm-tools/lib/include/vm_basic_asm_x86.h1
-rw-r--r--open-vm-tools/lib/include/vm_basic_asm_x86_64.h18
-rw-r--r--open-vm-tools/lib/include/vm_basic_asm_x86_common.h327
-rw-r--r--open-vm-tools/lib/include/vm_basic_defs.h94
-rw-r--r--open-vm-tools/lib/include/vm_basic_math.h83
-rw-r--r--open-vm-tools/lib/include/vm_basic_types.h164
-rw-r--r--open-vm-tools/lib/include/vm_device_version.h12
-rw-r--r--open-vm-tools/lib/include/vm_legal.h4
-rw-r--r--open-vm-tools/lib/include/vm_product.h101
-rw-r--r--open-vm-tools/lib/include/vm_product_versions.h96
-rw-r--r--open-vm-tools/lib/include/vm_tools_version.h96
-rw-r--r--open-vm-tools/lib/include/vmci_defs.h12
-rw-r--r--open-vm-tools/lib/include/vmsupport.h20
-rw-r--r--open-vm-tools/lib/include/vmware/guestrpc/capabilities.h20
-rw-r--r--open-vm-tools/lib/include/vmware/guestrpc/timesync.h2
-rw-r--r--open-vm-tools/lib/include/vmware/tools/log.h32
-rw-r--r--open-vm-tools/lib/include/vmware/tools/plugin.h14
-rw-r--r--open-vm-tools/lib/include/vmware/tools/utils.h18
-rw-r--r--open-vm-tools/lib/include/vthreadBase.h1
-rw-r--r--open-vm-tools/lib/include/win32util.h112
-rw-r--r--open-vm-tools/lib/include/wiper.h1
-rw-r--r--open-vm-tools/lib/include/x86_basic_defs.h11
-rw-r--r--open-vm-tools/lib/include/x86cpuid.h270
-rw-r--r--open-vm-tools/lib/include/x86cpuid_asm.h6
-rw-r--r--open-vm-tools/lib/lock/ul.c191
-rw-r--r--open-vm-tools/lib/lock/ulBarrier.c19
-rw-r--r--open-vm-tools/lib/lock/ulCondVar.c26
-rw-r--r--open-vm-tools/lib/lock/ulExcl.c353
-rw-r--r--open-vm-tools/lib/lock/ulInt.h107
-rw-r--r--open-vm-tools/lib/lock/ulIntShared.h11
-rw-r--r--open-vm-tools/lib/lock/ulRW.c229
-rw-r--r--open-vm-tools/lib/lock/ulRec.c481
-rw-r--r--open-vm-tools/lib/lock/ulSema.c200
-rw-r--r--open-vm-tools/lib/lock/ulStats.c328
-rw-r--r--open-vm-tools/lib/message/message.c140
-rw-r--r--open-vm-tools/lib/misc/Makefile.am1
-rw-r--r--open-vm-tools/lib/misc/Makefile.in9
-rw-r--r--open-vm-tools/lib/misc/base64.c73
-rw-r--r--open-vm-tools/lib/misc/codeset.c22
-rw-r--r--open-vm-tools/lib/misc/codesetBase.c2
-rw-r--r--open-vm-tools/lib/misc/codesetOld.c8
-rw-r--r--open-vm-tools/lib/misc/dynbuf.c38
-rw-r--r--open-vm-tools/lib/misc/escape.c48
-rw-r--r--open-vm-tools/lib/misc/hashTable.c36
-rw-r--r--open-vm-tools/lib/misc/hostType.c203
-rw-r--r--open-vm-tools/lib/misc/hostinfoPosix.c74
-rw-r--r--open-vm-tools/lib/misc/hostname.c14
-rw-r--r--open-vm-tools/lib/misc/idLinux.c4
-rw-r--r--open-vm-tools/lib/misc/iovector.c20
-rw-r--r--open-vm-tools/lib/misc/msgList.c12
-rw-r--r--open-vm-tools/lib/misc/posixDlopen.c4
-rw-r--r--open-vm-tools/lib/misc/posixInt.h31
-rw-r--r--open-vm-tools/lib/misc/posixPosix.c187
-rw-r--r--open-vm-tools/lib/misc/posixPwd.c20
-rw-r--r--open-vm-tools/lib/misc/random.c18
-rw-r--r--open-vm-tools/lib/misc/sha1.c283
-rw-r--r--open-vm-tools/lib/misc/sleep.c92
-rw-r--r--open-vm-tools/lib/misc/strutil.c8
-rw-r--r--open-vm-tools/lib/misc/timeutil.c247
-rw-r--r--open-vm-tools/lib/misc/util_misc.c155
-rw-r--r--open-vm-tools/lib/misc/vthreadBase.c33
-rw-r--r--open-vm-tools/lib/netUtil/netUtilLinux.c81
-rw-r--r--open-vm-tools/lib/nicInfo/nicInfoPosix.c2
-rw-r--r--open-vm-tools/lib/panic/panic.c42
-rw-r--r--open-vm-tools/lib/pollGtk/pollGtk.c10
-rw-r--r--open-vm-tools/lib/printer/Makefile.in532
-rw-r--r--open-vm-tools/lib/printer/printer.c399
-rw-r--r--open-vm-tools/lib/procMgr/procMgrPosix.c107
-rw-r--r--open-vm-tools/lib/procMgr/procMgrSolaris.c81
-rw-r--r--open-vm-tools/lib/rpcChannel/rpcChannel.c22
-rw-r--r--open-vm-tools/lib/rpcIn/rpcin.c100
-rw-r--r--open-vm-tools/lib/rpcOut/rpcout.c291
-rw-r--r--open-vm-tools/lib/rpcVmx/rpcvmx.c14
-rw-r--r--open-vm-tools/lib/slashProc/net.c3
-rw-r--r--open-vm-tools/lib/string/str.c46
-rw-r--r--open-vm-tools/lib/stubs/Makefile.am2
-rw-r--r--open-vm-tools/lib/stubs/Makefile.in12
-rw-r--r--open-vm-tools/lib/stubs/stub-config.c9
-rw-r--r--open-vm-tools/lib/stubs/stub-debug.c46
-rw-r--r--open-vm-tools/lib/stubs/stub-panic.c57
-rw-r--r--open-vm-tools/lib/syncDriver/syncDriverLinux.c11
-rw-r--r--open-vm-tools/lib/syncDriver/syncDriverPosix.c4
-rw-r--r--open-vm-tools/lib/syncDriver/vmSyncDriver.c2
-rw-r--r--open-vm-tools/lib/system/systemLinux.c8
-rw-r--r--open-vm-tools/lib/unicode/unicodeCommon.c8
-rw-r--r--open-vm-tools/lib/unicode/unicodeICU.c42
-rw-r--r--open-vm-tools/lib/unicode/unicodeInt.h14
-rw-r--r--open-vm-tools/lib/unicode/unicodeSimpleBase.c135
-rw-r--r--open-vm-tools/lib/unicode/unicodeSimpleCaseFolding.c2
-rw-r--r--open-vm-tools/lib/unicode/unicodeSimpleOperations.c75
-rw-r--r--open-vm-tools/lib/unicode/unicodeSimpleTransforms.c38
-rw-r--r--open-vm-tools/lib/unicode/unicodeStatic.c22
-rw-r--r--open-vm-tools/lib/user/util.c41
-rw-r--r--open-vm-tools/lib/user/utilBacktrace.c11
-rw-r--r--open-vm-tools/lib/wiper/wiperPosix.c5
-rw-r--r--open-vm-tools/libhgfs/Makefile.am3
-rw-r--r--open-vm-tools/libhgfs/Makefile.in5
-rw-r--r--open-vm-tools/libvmtools/vmtoolsConfig.c13
-rw-r--r--open-vm-tools/libvmtools/vmtoolsLog.c539
-rw-r--r--open-vm-tools/libvmtools/vmxLogger.c8
-rw-r--r--open-vm-tools/modules/freebsd/vmblock/subr.c2
-rw-r--r--open-vm-tools/modules/freebsd/vmblock/vfsops.c2
-rw-r--r--open-vm-tools/modules/freebsd/vmblock/vnops.c2
-rw-r--r--open-vm-tools/modules/freebsd/vmmemctl/os.c22
-rw-r--r--open-vm-tools/modules/linux/dkms.conf2
-rw-r--r--open-vm-tools/modules/linux/dkms.sh5
-rw-r--r--open-vm-tools/modules/linux/shared/autoconf/dalias.c48
-rw-r--r--open-vm-tools/modules/linux/shared/autoconf/dalias1.c50
-rw-r--r--open-vm-tools/modules/linux/shared/autoconf/file_operations_flush.c2
-rw-r--r--open-vm-tools/modules/linux/shared/autoconf/truncate_pagecache.c52
-rw-r--r--open-vm-tools/modules/linux/shared/driverLog.c2
-rw-r--r--open-vm-tools/modules/linux/shared/driverLog.h2
-rw-r--r--open-vm-tools/modules/linux/shared/kernelStubsLinux.c40
-rw-r--r--open-vm-tools/modules/linux/shared/kernelStubsSal.h4
-rw-r--r--open-vm-tools/modules/linux/shared/vmci_call_defs.h2
-rw-r--r--open-vm-tools/modules/linux/shared/vmci_defs.h12
-rw-r--r--open-vm-tools/modules/linux/shared/vmci_iocontrols.h4
-rw-r--r--open-vm-tools/modules/linux/shared/vmci_kernel_if.h16
-rw-r--r--open-vm-tools/modules/linux/vmci/common/vmciContext.c114
-rw-r--r--open-vm-tools/modules/linux/vmci/common/vmciContext.h7
-rw-r--r--open-vm-tools/modules/linux/vmci/common/vmciEvent.c14
-rw-r--r--open-vm-tools/modules/linux/vmci/common/vmciQueuePair.c2
-rw-r--r--open-vm-tools/modules/linux/vmci/linux/driver.c2
-rw-r--r--open-vm-tools/modules/linux/vmci/linux/vmci_version.h6
-rw-r--r--open-vm-tools/modules/linux/vmci/shared/pgtbl.h20
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/Makefile.kernel21
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/dir.c12
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/file.c22
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/filesystem.c24
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/fsutil.c947
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/fsutil.h41
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/inode.c31
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/module.h28
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/page.c1217
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/request.h2
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/transport.c12
-rw-r--r--open-vm-tools/modules/linux/vmhgfs/vmhgfs_version.h6
-rw-r--r--open-vm-tools/modules/linux/vsock/linux/af_vsock.c54
-rw-r--r--open-vm-tools/modules/linux/vsock/linux/notify.c2
-rw-r--r--open-vm-tools/modules/linux/vsock/linux/notify.h2
-rw-r--r--open-vm-tools/modules/linux/vsock/linux/notifyQState.c2
-rw-r--r--open-vm-tools/modules/linux/vsock/linux/vsockCommon.h2
-rw-r--r--open-vm-tools/modules/linux/vsock/linux/vsockSocketWrapper.h2
-rw-r--r--open-vm-tools/modules/linux/vsock/linux/vsock_version.h8
-rw-r--r--open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c60
-rw-r--r--open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h6
-rw-r--r--open-vm-tools/modules/shared/vmmemctl/balloonInt.h7
-rw-r--r--open-vm-tools/modules/shared/vmmemctl/balloon_def.h50
-rw-r--r--open-vm-tools/modules/shared/vmmemctl/dbllnklst.h20
-rw-r--r--open-vm-tools/modules/shared/vmmemctl/kernelStubsSal.h173
-rw-r--r--open-vm-tools/modules/shared/vmmemctl/os.h10
-rw-r--r--open-vm-tools/modules/shared/vmmemctl/vmballoon.c439
-rw-r--r--open-vm-tools/modules/shared/vmmemctl/vmballoon.h52
-rw-r--r--open-vm-tools/modules/shared/vmxnet/eth_public.h2
-rw-r--r--open-vm-tools/modules/shared/vmxnet/net.h8
-rw-r--r--open-vm-tools/modules/shared/vmxnet/upt1_defs.h2
-rw-r--r--open-vm-tools/modules/shared/vmxnet/vmnet_def.h4
-rw-r--r--open-vm-tools/modules/shared/vmxnet/vmxnet2_def.h19
-rw-r--r--open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h29
-rw-r--r--open-vm-tools/modules/shared/vmxnet/vmxnet_def.h2
-rw-r--r--open-vm-tools/modules/solaris/vmhgfs/filesystem.c7
-rw-r--r--open-vm-tools/modules/solaris/vmhgfs/filesystem.h11
-rw-r--r--open-vm-tools/modules/solaris/vmmemctl/os.c12
-rw-r--r--open-vm-tools/modules/solaris/vmmemctl/vmballoon_kstats.c18
-rw-r--r--open-vm-tools/scripts/common/vm-support19
-rw-r--r--open-vm-tools/scripts/linux/pam.d/vmtoolsd6
-rw-r--r--open-vm-tools/services/plugins/desktopEvents/x11Lock.c2
-rw-r--r--open-vm-tools/services/plugins/dndcp/copyPasteDnDWrapper.cpp8
-rw-r--r--open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp2
-rw-r--r--open-vm-tools/services/plugins/dndcp/dnd/dnd.h26
-rw-r--r--open-vm-tools/services/plugins/dndcp/dnd/dndCPMsgV4.c2
-rw-r--r--open-vm-tools/services/plugins/dndcp/dnd/dndCommon.c178
-rw-r--r--open-vm-tools/services/plugins/dndcp/dnd/dndInt.h13
-rw-r--r--open-vm-tools/services/plugins/dndcp/dnd/dndLinux.c45
-rw-r--r--open-vm-tools/services/plugins/dndcp/dnd/dndMsg.c6
-rw-r--r--open-vm-tools/services/plugins/dndcp/dndUIX11.cpp15
-rw-r--r--open-vm-tools/services/plugins/dndcp/stringxx/autoCPtr.hh95
-rw-r--r--open-vm-tools/services/plugins/dndcp/stringxx/string.cc160
-rw-r--r--open-vm-tools/services/plugins/dndcp/stringxx/string.hh34
-rw-r--r--open-vm-tools/services/plugins/dndcp/stringxx/ubstr_t.hh39
-rw-r--r--open-vm-tools/services/plugins/dndcp/xutils/xutils.cc1
-rw-r--r--open-vm-tools/services/plugins/grabbitmqProxy/grabbitmqProxyPlugin.c9
-rw-r--r--open-vm-tools/services/plugins/guestInfo/diskInfo.c6
-rw-r--r--open-vm-tools/services/plugins/guestInfo/guestInfoInt.h29
-rw-r--r--open-vm-tools/services/plugins/guestInfo/guestInfoServer.c786
-rw-r--r--open-vm-tools/services/plugins/guestInfo/perfMonLinux.c1162
-rw-r--r--open-vm-tools/services/plugins/hgfsServer/hgfsPlugin.c7
-rw-r--r--open-vm-tools/services/plugins/powerOps/powerOps.c29
-rw-r--r--open-vm-tools/services/plugins/resolutionSet/resolutionSet.c4
-rw-r--r--open-vm-tools/services/plugins/resolutionSet/resolutionX11.c32
-rw-r--r--open-vm-tools/services/plugins/timeSync/timeSync.c17
-rw-r--r--open-vm-tools/services/plugins/vix/foundryToolsDaemon.c135
-rw-r--r--open-vm-tools/services/plugins/vix/vixPlugin.c2
-rw-r--r--open-vm-tools/services/plugins/vix/vixTools.c875
-rw-r--r--open-vm-tools/services/plugins/vix/vixToolsInt.h2
-rw-r--r--open-vm-tools/services/plugins/vmbackup/README39
-rw-r--r--open-vm-tools/services/plugins/vmbackup/nullProvider.c38
-rw-r--r--open-vm-tools/services/plugins/vmbackup/stateMachine.c102
-rw-r--r--open-vm-tools/services/plugins/vmbackup/syncDriverOps.c114
-rw-r--r--open-vm-tools/services/plugins/vmbackup/vmBackupInt.h31
-rw-r--r--open-vm-tools/services/vmtoolsd/cmdLine.c6
-rw-r--r--open-vm-tools/services/vmtoolsd/l10n/de.vmsg2
-rw-r--r--open-vm-tools/services/vmtoolsd/l10n/ja.vmsg2
-rw-r--r--open-vm-tools/services/vmtoolsd/l10n/ko.vmsg2
-rw-r--r--open-vm-tools/services/vmtoolsd/mainLoop.c8
-rw-r--r--open-vm-tools/services/vmtoolsd/mainPosix.c2
-rw-r--r--open-vm-tools/services/vmtoolsd/pluginMgr.c4
-rw-r--r--open-vm-tools/services/vmtoolsd/toolsRpc.c59
-rw-r--r--open-vm-tools/toolbox/Makefile.am1
-rw-r--r--open-vm-tools/toolbox/Makefile.in20
-rw-r--r--open-vm-tools/toolbox/l10n/de.vmsg32
-rw-r--r--open-vm-tools/toolbox/l10n/ja.vmsg32
-rw-r--r--open-vm-tools/toolbox/l10n/ko.vmsg30
-rw-r--r--open-vm-tools/toolbox/l10n/zh_CN.vmsg38
-rw-r--r--open-vm-tools/toolbox/toolbox-cmd.c2
-rw-r--r--open-vm-tools/toolbox/toolboxCmdInt.h1
-rw-r--r--open-vm-tools/toolbox/toolboxcmd-logging.c286
-rw-r--r--open-vm-tools/toolbox/toolboxcmd-shrink.c1
-rw-r--r--open-vm-tools/vgauth/cli/l10n/de.vmsg52
-rw-r--r--open-vm-tools/vgauth/cli/l10n/es.vmsg20
-rw-r--r--open-vm-tools/vgauth/cli/l10n/fr.vmsg52
-rw-r--r--open-vm-tools/vgauth/cli/l10n/it.vmsg18
-rw-r--r--open-vm-tools/vgauth/cli/l10n/ja.vmsg52
-rw-r--r--open-vm-tools/vgauth/cli/l10n/ko.vmsg46
-rw-r--r--open-vm-tools/vgauth/cli/l10n/zh_CN.vmsg46
-rw-r--r--open-vm-tools/vgauth/cli/l10n/zh_TW.vmsg6
-rw-r--r--open-vm-tools/vgauth/cli/main.c5
-rw-r--r--open-vm-tools/vgauth/common/certverify.c69
-rw-r--r--open-vm-tools/vgauth/common/certverify.h2
-rw-r--r--open-vm-tools/vgauth/lib/authPosix.c26
-rw-r--r--open-vm-tools/vgauth/lib/common.c6
-rw-r--r--open-vm-tools/vgauth/lib/l10n/de.vmsg6
-rw-r--r--open-vm-tools/vgauth/lib/l10n/fr.vmsg6
-rw-r--r--open-vm-tools/vgauth/lib/l10n/it.vmsg4
-rw-r--r--open-vm-tools/vgauth/lib/l10n/ja.vmsg6
-rw-r--r--open-vm-tools/vgauth/lib/l10n/ko.vmsg6
-rw-r--r--open-vm-tools/vgauth/service/l10n/de.vmsg28
-rw-r--r--open-vm-tools/vgauth/service/l10n/es.vmsg54
-rw-r--r--open-vm-tools/vgauth/service/l10n/fr.vmsg24
-rw-r--r--open-vm-tools/vgauth/service/l10n/it.vmsg54
-rw-r--r--open-vm-tools/vgauth/service/l10n/ja.vmsg28
-rw-r--r--open-vm-tools/vgauth/service/l10n/ko.vmsg24
-rw-r--r--open-vm-tools/vgauth/service/l10n/zh_CN.vmsg28
-rw-r--r--open-vm-tools/vgauth/service/log.c3
-rw-r--r--open-vm-tools/vgauth/serviceImpl/alias.c2
-rw-r--r--open-vm-tools/vgauth/serviceImpl/service.c2
-rw-r--r--open-vm-tools/vgauth/serviceImpl/serviceInt.h1
-rw-r--r--open-vm-tools/vgauth/serviceImpl/ticket.c25
-rw-r--r--open-vm-tools/vgauth/serviceImpl/verify.c29
-rw-r--r--open-vm-tools/vmhgfs-fuse/COPYING502
-rw-r--r--open-vm-tools/vmhgfs-fuse/Makefile.am55
-rw-r--r--open-vm-tools/vmhgfs-fuse/bdhandler.c255
-rw-r--r--open-vm-tools/vmhgfs-fuse/bdhandler.h32
-rw-r--r--open-vm-tools/vmhgfs-fuse/cache.c458
-rw-r--r--open-vm-tools/vmhgfs-fuse/cache.h34
-rw-r--r--open-vm-tools/vmhgfs-fuse/config.c521
-rw-r--r--open-vm-tools/vmhgfs-fuse/config.h42
-rw-r--r--open-vm-tools/vmhgfs-fuse/dir.c965
-rw-r--r--open-vm-tools/vmhgfs-fuse/file.c1471
-rw-r--r--open-vm-tools/vmhgfs-fuse/file.h45
-rw-r--r--open-vm-tools/vmhgfs-fuse/filesystem.c290
-rw-r--r--open-vm-tools/vmhgfs-fuse/filesystem.h49
-rw-r--r--open-vm-tools/vmhgfs-fuse/fsutil.c784
-rw-r--r--open-vm-tools/vmhgfs-fuse/fsutil.h145
-rw-r--r--open-vm-tools/vmhgfs-fuse/link.c222
-rw-r--r--open-vm-tools/vmhgfs-fuse/linux/list.h263
-rw-r--r--open-vm-tools/vmhgfs-fuse/main.c1378
-rw-r--r--open-vm-tools/vmhgfs-fuse/module.h132
-rw-r--r--open-vm-tools/vmhgfs-fuse/request.c448
-rw-r--r--open-vm-tools/vmhgfs-fuse/request.h138
-rw-r--r--open-vm-tools/vmhgfs-fuse/session.c418
-rw-r--r--open-vm-tools/vmhgfs-fuse/session.h30
-rw-r--r--open-vm-tools/vmhgfs-fuse/transport.c421
-rw-r--r--open-vm-tools/vmhgfs-fuse/transport.h63
-rw-r--r--open-vm-tools/vmhgfs-fuse/vmhgfs_version.h32
-rw-r--r--open-vm-tools/vmware-user-suid-wrapper/wrapper.h2
401 files changed, 28197 insertions, 10228 deletions
diff --git a/open-vm-tools/ChangeLog b/open-vm-tools/ChangeLog
index 43269d90..ad04b12f 100644
--- a/open-vm-tools/ChangeLog
+++ b/open-vm-tools/ChangeLog
@@ -1,3 +1,626 @@
+open-vm-tools-10.0.0 build 3000743
+
+* Common versioning
+
+* Quiesced snapshots
+
+* hgfs-fuse
+
+* Logging changes
+
+* AsyncSocket changes
+
+* Change ASSERT macros to VERIFY
+
+* Additional locking fixes and optimizations
+
+* Unicode type and macro cleanup
+
+* Change glib logging in RpcChannel to use Debug/Warning/Panic.
+
+* Clean up HGFS server unpack file name V3 arguments
+
+* Fix nested logging for VmxLogger with vsocket channel.
+
+* Compile mac-rdpvcbridge from cart-dev
+
+* Implement VMware Tools for ESXi 6.0 guests.
+
+* Get rid of ASSERT_ALWAYS_AVAILABLE
+
+* Get rid of ASSERT_LENGTH.
+
+* Move ASSERT_OR_IN_PANIC() from public/vm_assert.h to vmkernel.
+
+* Make lib/location product-agnostic
+
+* desktopEvents: Leave libICE rug firmly under libSM.
+
+* Remove SLPv2
+
+* Provide a kill-switch for using vsocket in RpcChannel.
+
+* Use binary search tree to map guest os string to guest os enum.
+
+* codeset: use icuDir instead of libDir
+
+* Remove NR_MPNS_PER_PAGE
+
+* Make FileIO_AtomicUpdate fail gracefully when File_FullPath fails.
+
+* Merge atomic FetchAndAdd64 with ReadAdd64.
+
+* Rename Atomic_FetchAdd, part 1.
+
+* AsyncSocket: Remove UDP socket support.
+
+* Introduce Id_IsSetUGid for detecting setuid/setgid binaries.
+
+* Update WS, player version numbers on *-main branch.
+
+* Integrate all VIX changes from hosted13-pd-rel to vmcore-main.
+
+* Rename Atomic_FetchAnd*, part 5.
+
+* Cache Tools conf path.
+
+* No more Atomic_Fetch.
+
+* Add configuring of the Windows core dump flags for the tools service
+
+* Temporary fix for PR 1111448.
+
+* Add surface logging to basicOps
+
+* Id_IsSetUGid fails to compile on Android.
+
+* Add devel backdoor command to run replays inside frobos tests.
+
+* Save registers earlier during Panic.
+
+* Prepare the HGFS Windows client to use VMCI transport header version 2
+
+* Get Mac OS system version from (Server|System)Version.plist
+
+* WebMKS plumbing: vmx side
+
+* Create new V2 of VMCI transport header
+
+* Minor logging cleanup in vmware-vprobe
+
+* Notify VMX when Toolsd is going down
+
+* Remove ovftool temporary fix.
+
+* Add /proc/interrupts and /proc/irq/* to vm-support
+
+* Remove HGFS from FreeBSD builds and packaging
+
+* Split DR6_ONES into DR6_DEFAULT and DR6_ONES
+
+* Add utilMem to Frobos
+
+* Support Intel RTM Debug behavior in VT mode.
+
+* MSG: Skip errno localization on unknown platforms.
+
+* Replace CPU_MemBarrier with Atomic_MFence
+
+* Prevent low privileged user from writable access to tools conf data
+
+* Change shutdown notification RPC failure message to debug.
+
+* Eliminate some "legacy IPC baggage".
+
+* Fix tools_obj_linux64 build (license file mismatch)
+
+* Convert the HGFS uses of ASSERT_DEVEL into ASSERT or remove
+
+* arm64 support in vm_basic_{types,defs}.h
+
+* Add an error function hook to PollDefault
+
+* arm64 support in vm_[basic_]asm.h
+
+* asyncWebSocket: improve rmks warning message when WebSocket connection fails due to bad SSL cert.
+
+* Implement MXUser semaphores on Mac OS with lib dispatch semaphores
+
+* Replace 3-clause BSD license template with 2-clause BSD license
+
+* vm_basic_{types,asm}.h: cleanup architecture #ifdefs
+
+* Add a surface flag for 16-byte image alignment in mobs
+
+* Change config.version from String to Long.
+
+* Fix HGFS server change notification packet handling.
+
+* Cleanup "vm_basic_defs.h"
+
+* vm_atomic: add ARM64 atomic operations.
+
+* Enable the HGFS VMCI VMX and HGFS server use the V2 header
+
+* Implement Devel ScreenShot command
+
+* Fix the HGFS protocol opcode to differentiate headers
+
+* vmkBoot: refactor serial, arm64 serial & panic.
+
+* vm_atomic: fix arm64 ReadIfWriteEqual atomics.
+
+* arm: bug fixes for uint*set implementations.
+
+* Rework the tools heartbeat code in the VMX.
+
+* vm_atomic: eliminate non-ASCII chars in comment.
+
+* Remove the incorrect immediate constraint from 64-bit atomic ops
+
+* Refactor code under guestinfo/getlib.
+
+* Remove __builtin_*_address(N) compile checks.
+
+* boot: misc. vmkernel changes to allow arm64 boot.c compile.
+
+* debug: move debug to main/x86, arm64 stubs.
+
+* prda/specialstack: refactor to split out arch deps, arm64 support.
+
+* Cleanup guestinfo plugin header dependency.
+
+* Change WSAAddressToString to WSAAddressToStringA
+
+* Handle EINVAL for preadv and pwritev.
+
+* Change GET_CURRENT_LOCATION definition.
+
+* Check if __GLIBC_PREREQ is defined before using it.
+
+* Add support for IOMMU guest addresses > 16TB.
+
+*
+
+* Fix Atomic_Read on ARMv7.
+
+* Create a trivial view when both the texture and the view are R24G8 class.
+
+* vm_atomic: fix ARM 32/64-bit Atomic_Read.
+
+* OvhdMem refactor + pull from vmioplugin branch
+
+* cpuset/vm_basic_asm: use standard clr/ctz primitives.
+
+* vm_basic_asm: fix windows build breakage.
+
+* vSock: Rename "VMCI Sockets".
+
+* Disable nullDriver by default and add a config switch to enable it.
+
+* First submit of the VDTI PCI Device.
+
+* Cleanup/Rationalize coreDump
+
+* vSock VMX: Introduce a separate sendCb field
+
+* Don't define g_info if it is available.
+
+* A virtual USB video device backend.
+
+* A virtual video device backend.
+
+* Skip freezing remote mounts.
+
+* lib/file: Various fixes to FileIOP(read|write)vInternal and FileIO_(Readv|Writev).
+
+* Use int 31 instruction to trigger an assert in the VMKernel
+
+* vm_basic_asm: fix uint32set for arm64.
+
+* Clean up of APIs used by the HGFS server library
+
+* Clean up the HGFS server shares interface to the HGFS server part II
+
+* Ignore disk UUIDs from the paths to be frozen.
+
+* Clean up the HGFS server use of the policy share enumeraton APIs
+
+* fix HostinfoGetOSShortName to support Debian 7.x
+
+* remove unnecessary constraints for ABSOLUTELY_NOINLINE define
+
+* More clean up the HGFS server manager, policy manager APIs
+
+* Remove MPN32 related macros.
+
+* lib/uuid: Add CreateRandomEFI, and cleanup
+
+* Fix buffer overflow in perfMonLinux
+
+* AsyncSocket: hostname/IP string connection functions should attempt both IPv4 and IPv6 connections.
+
+* lib/lock: lock tracking tree optimization
+
+* Fast send on the asynNamedPipe if Write completes synchronously.
+
+* increase MAX_MPN to 38 bits
+
+* finish conversion of invalid_mpn64 and max_mpn64
+
+* Change Mul64x3264 family of functions to round instead of truncating
+
+* Add CACHELINE_SIZE to vm_basic_defs.h.
+
+* Memory is accessed after being freed in function
+
+* Add some debug noise to RPCs received in guest.
+
+* Add SMAP support to MMU page walkers and MonTLB
+
+* lib/file: File_Rotate needs some protection
+
+* Hgfs VMCI: move packet max size to the correct location
+
+* Hgfs Server: remove transport only header file from the server.
+
+* Log errors in RandomBytesWin32.
+
+* Defer the RunScript cleanup when VIX commands are restricted.
+
+* Add support in resolution set to log multiple sessions in RDSH.
+
+* Make Clamped_SAdd32 more robust against compiler options
+
+* Compare the remote FS type strings the right way.
+
+* VIX plugin under vmusr should not register for TOOLS_CORE_SIG_IO_FREEZE.
+
+* Add runtime macros to check type of tools service.
+
+* vm_atomic: remove unfenced atomic operations.
+
+* vm_atomic: LOCK-like semantics for arm64 atomics.
+
+* refcount/vm_basic_asm: multi-architecture memory barriers.
+
+* Hgfs Server: Fix unpacking of protocol header unused fields
+
+* Enlarge MAX_IFACES to ensure vmtools could get a valid GOS IP throguh NetUtil_GetPrimaryIP().
+
+* Change BPN to be a 64 bit type.
+
+* lib/lock: MXUser_Control* -> typed functions [trivial?]
+
+* fix bad error
+
+* ARM64: Add more basic assembler support
+
+* Guest Tools: Add memNeeded for Windows and Linux and handle versioning
+
+* Fix incorrect LRU file accounting for memNeeded on Linux
+
+* Change the bit representation of BPN to make way for NVM.
+
+* tools perf mon: collect more stats from /proc/meminfo
+
+* Remove vmxwifi.sys and macWireless_defs.h
+
+* tools perf mon: refactor
+
+* tools data collection: Collect all of the new Linux data
+
+* Guest stats: fix the time base
+
+* gos tables: Table must be sorted; reinsert "coreos-64" accordingly
+
+* guest performance data: no need to have a maximum RPC transfer size
+
+* guest perf stats: replumb GuestInfo_PerfMon
+
+* guest perf stats: GuestInfo_PerfMon builds the RPC data itself
+
+* guest perf data: collect the Linux data
+
+* guest perf data: return the new protocol
+
+* guest perf stats: ice the cake (add some polish)
+
+* guest perf stats: Linux goes to the new format
+
+* Hgfs Posix Server: fix the writes to not exceed max file size
+
+* Stick backdoor behavior after vSocket connection failure.
+
+* Hgfs Posix Server: fix Solaris tools obj builds for log statements
+
+* Fix memory leak in hgfs server.
+
+* Implement QuadBlit for DX11Renderer.
+
+* Add feature-specific RDE Dev Targets - folderRedirection, tsmmr, viewMP
+
+* MX_Lock should not use HLE on unpatched Haswell systems
+
+* Hgfs Posix Server: add some useful logging for symlink names
+
+* lib/file: Don't leak a filename in FileRotateByRenumber.
+
+* Hgfs Posix Server: add more useful logging to open
+
+* Hgfs Posix Server: fix open requests failing EAGAIN (EWOULDBLOCK)
+
+* Sometimes channel can be NULL, this will make vmtools panic.
+
+* lib: misc/sig support for arm64 (redux).
+
+* HostType: stop using sysctl
+
+* authPosix: use getspent when using shadow password, but not PAM
+
+* Added protocol selection to bora AsyncWebSocket.- Changed VNC Client offer 'vmware-vvc' protocol as an additional protocol.
+
+* Enable 3D with DX11Renderer and port over the existing PROTOTYPE RenderOps functions.
+
+* Create the support dir under /tmp instead of CWD.
+
+* Disable NullDriver backend only for forceQuiece case.
+
+* Hgfs Server: fix malformed symlink creation requests
+
+* Hgfs Server: fix check malformed read packets
+
+* Fix Ubuntu errors in the vm-support script.
+
+* Expose BDOOR_CMD_VCPU_MMIO_HONORS_PAT to guest.
+
+* Add optional websocket protocols parameter to AsyncSocket_ListenWebSocketUDS. If NULL then default (legacy) protocols are used.
+
+* Allow the network script to bring each individual interface up/down.
+
+* deployPkg plugin: make deployPkg.cpp build as C or C++
+
+* GOSTable: Plumb vmkernel6 as a separate bit
+
+* add deployPkg files to open-vm-tools
+
+* Introduce mkfsPmem, libpmem for managing pmem resources via the kernel from user-space.
+
+* Allow to queue MCE requests form the kernel to the VMM.
+
+* HGFS: Remove R/R
+
+* Replace PUSHF/POPF with STAC/NOP when setting EFLAGS.AC
+
+* lib/file: hostd crashes in assertion failure due to file list
+
+* Tools: Create GuestInfo_GetPrimaryIP as a IPv6 compliant version of NetUtil_GetPrimaryIP
+
+* Remove memNeeded calculation from the guest tools
+
+* Move SIZE_xxBITS to common architecture file.
+
+* GOSTable: Windows 10 as a unique guest
+
+* Set _FILE_OFFSET_BITS=64 for Solaris
+
+* Plumbing to expose (whitelisted) vsi-based stats in guest
+
+* Assorted _FILE_OFFSET_BITS=64 / _LARGEFILE64_SOURCE fixups
+
+* Serial: [2/16] Serial8250 - refactor into generic and platform parts.
+
+* lib/log: Improve the level filtering implementation and documentation
+
+* lib/log: no need to "blip" the lock
+
+* lib/misc: header clean up
+
+* Add 16 bits atomics to vm_atomic.h.
+
+* Add 16 bits atomics for arm64
+
+* Clean up some file headers
+
+* Begin plumbing guest mks stats out to the host.
+
+* lib/log: improved documentation in log.h
+
+* Converting MPN to MPN32.
+
+* Reimplement guestproxycerttool.pl in C.
+
+* Atomic Boolean support
+
+* Add grabbitmqProxy plugin to open-vm-tools.
+
+* Windows 10: an all Windows 10 macro
+
+* Remove some vacuous FileIO usage
+
+* Introducing 64-bit MPN type.
+
+* mks: add shared-secret authentication for Blast websocket connections
+
+* Windows 10: add macros for all 32 and all 64 bit
+
+* Add guestproxycerttool (C-implementation) to open-vm-tools and OSPs.
+
+* cleanup app balloon in vmm, vmx, and parts of vmkernel
+
+* Honour panic.breakOnPanic on Posix.
+
+* hashTable: free function work like our other free functions
+
+* Introduce certificate hash verification in blast native clients.
+
+* Forward declare sslverifyparam in ssldirect.h
+
+* asyncWebsocket: move WebSocketHandshakeState into asyncWebSocket.c
+
+* RecordReplayRemoval: make RR go away from automation tools.
+
+* tools: improved memNeeded
+
+* guest stats: Use DynBufs
+
+* guest tools: a bit of consolidation
+
+* guest stats: rates in pages per second
+
+* Guest stats: Dynamically capture stats in Linux
+
+* guestStats: optimize memory allocation
+
+* guest stats: Linux deals with overflow
+
+* guest stats: consistent open file failure messages
+
+* GuestStat: improve function header
+
+* GuestStat: more function header cleanup
+
+* Stop publishing guest stats from VSI/GuestMemInfo structure.
+
+* Guest Stats: extensible reporting
+
+* Use new #define _DEFAULT_SOURCE to build open-vm-tools.
+
+* Publish Windows guest stats via V5 format
+
+* Guest stats: Only populate Linux legacy values that have been consumed
+
+* guest stats: Linux publish names as defines
+
+* Windows stat code cleanup
+
+* GuestStat: official registed the build in names
+
+* Adjust lock ranks for IO filters.
+
+* asyncWebSocket: remove hybi designator and consolidate code
+
+* asyncWebSocket: simplify protocol lists and framing
+
+* asyncSocket: simplify the interface for specifying websocket protocols
+
+* GuestStat: Name data is properly name string
+
+* lib/misc: Support Util_IsAbsolutePath on Solaris and FreeBSD
+
+* Hgfs Server: fix unpack of file name args for directory open
+
+* Minor updates to windows stat code
+
+* GuestStats: Better data validation and names
+
+* Debug log messages and minor fixes.
+
+* Add TLS caching for gettid calls on Linux
+
+* Add File_DeleteDirectoryContent.
+
+* Allow vm-support script execution only for root user.
+
+* GuestStats: rationalize the stat datum bits
+
+* No more MPN64 type.
+
+* Gettid TLS: fix coredumping
+
+* sigPosix scrub: more consistent self-signal behavior and remove unused code
+
+* Guest Stats: fix alphabetization
+
+* Publish stats for Windows pagefile size and used subset in KB
+
+* GuestOps: Set file ownership before setting file permissions.
+
+* GuestStats: no time units.
+
+* GuestSDK: remove vmtools.dll/so dependency
+
+* Use new generic way to collect guest stats and remove unused legacy guest stats.
+
+* Remove vmioplugin.
+
+* Use GOnce in pollGtk instead of a static mutex.
+
+* Update hgfsServer alias code.
+
+* Inline ASM for rotate left/right instruction
+
+* Add backdoor command to restrict vmmouse
+
+* Add Posix File to hgfsURI
+
+* lib/file: FileSleeper must really sleep
+
+* Fix unnecessary cast
+
+* Add LIKELY/UNLIKELY into MXUserRec
+
+* Fix argument order for InterlockedCompareExchange8
+
+* rmks/ssl: change SSL verification for View/Blast RMKS connections to reject mismatched thumbprint always
+
+* GuestStats: Linux active/inactive anon buffers
+
+* GuestStats: order the linux stats
+
+* GuestStats: Clean up include file
+
+* Hgfs Server: enhance logging for packet request ID
+
+* Allow RpcVMX_LogV to run without calling malloc.
+
+* Update the stat IDs list.
+
+* Don't mount alias target volumes while resolving HGFS file attributes
+
+* Remove the executable bit from various source files
+
+* add some improved cert debug noise
+
+* Basic infrastructure support for guestIntegrity backdoor calls.
+
+* Implement MXUser semaphores on Mac OS with lib dispatch semaphores
+
+* Add a backdoor command for mksStats snapshots.
+
+* add vmhgfs-fuse to open-vm-tools
+
+* vm_basic_defs/gdb: use non-builtin offsetof for vmk gdb macros.
+
+* Implement MXUserEvent
+
+* Remove updateAgent code.
+
+* Change default sampling rate for guest stats to 20 seconds.
+
+* Include cstring to avoid 'memset not in scope' error.
+
+* Remove guestStats that are beyond 60u1 scope.
+
+* Fixes for use_after_free, double_free and double_close.
+
+* Use a global lock for protecting gLoggingStopped.
+
+* change default debugging level and location
+
+* adjust logging noise for vmtoolsd
+
+* clean up debug & warning messages in guestInfo plugin
+
+* clean up logging in vix plugin
+
+* recategorize powerOps logging messages
+
+* gather new default Tools logs with vm-support
+
+* add toolbox-cmd support for log`
+
+open-vm-tools-9.10.2 build 2822639
* Use new #define _DEFAULT_SOURCE to build OVT.
diff --git a/open-vm-tools/LICENSE b/open-vm-tools/LICENSE
new file mode 100644
index 00000000..18dd5f13
--- /dev/null
+++ b/open-vm-tools/LICENSE
@@ -0,0 +1,406 @@
+LICENSE
+
+open-vm-tools 10.0.0
+
+The Linux kernel modules are released under the GPL v2, a majority of the user level components are released under the LGPL v2.1, and the SVGA and mouse drivers are released under the X11 license.
+
+Copyright © 2007-2015 VMware, Inc. All rights reserved.
+
+=========================================================================
+GNU GENERAL PUBLIC LICENSE
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+=========
+
+GNU LESSER GENERAL PUBLIC LICENSE
+Version 2.1, February 1999
+
+Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.]
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
+
+This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
+
+When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
+
+To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
+
+For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
+
+We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.
+
+To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
+
+Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.
+
+Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
+
+When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
+
+We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
+
+For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
+
+In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
+
+Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
+
+The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
+
+A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
+
+The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
+
+"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
+
+1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+a) The modified work must itself be a software library.
+b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
+c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
+d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
+(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.
+
+Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
+
+This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
+
+4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
+
+If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
+
+5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
+
+However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
+
+When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
+
+If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
+
+Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
+
+6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
+
+You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
+a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
+b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
+c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
+d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
+e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
+
+For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
+
+7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
+a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
+b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
+
+8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+
+9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
+
+10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
+
+11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
+
+14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+NO WARRANTY
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+=========
+
+X11 License
+
+Copyright (c) <year> <copyright holders>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+========
+
+open-vm-tools v10.0.0 includes a number of subcomponents with separate copyright notices and license terms. Your use of the source code for these subcomponents is subject to the terms and conditions of the following licenses.
+
+
+
+SECTION 1: BSD-STYLE, MIT-STYLE, OR SIMILAR STYLE LICENSES
+
+ >>> base64.c-none
+ >>> convertutf.c/.h from unicode, inc.-none
+ >>> freebsd-1.72
+ >>> icu4c-4.4.1
+ >>> unicode-5.0
+
+------ SECTION 1: BSD-STYLE, MIT-STYLE, OR SIMILAR STYLE LICENSES ------
+
+BSD-STYLE, MIT-STYLE, OR SIMILAR STYLE LICENSES are applicable to the following component(s).
+
+>>> base64.c-none
+
+base64.c -- routines to encode/decode base64 data
+$OpenLDAP: pkg/ldap/libraries/liblutil/base64.c,v 1.15 2006/01/03 22:12:11 kurt Exp $ /
+This work is part of OpenLDAP Software <http://www.openldap.org/>.
+
+Copyright 1998-2006 The OpenLDAP Foundation.
+Portions Copyright 1998-2003 Kurt D. Zeilenga.
+Portions Copyright 1995 IBM Corporation.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted only as authorized by the OpenLDAP
+Public License.
+
+A copy of this license is available in the file LICENSE in the
+top-level directory of the distribution or, alternatively, at
+<http://www.OpenLDAP.org/license.html>.
+The OpenLDAP Public License
+Version 2.8, 17 August 2003
+
+Redistribution and use of this software and associated documentation
+("Software"), with or without modification, are permitted provided
+that the following conditions are met:
+
+1. Redistributions in source form must retain copyright statements
+and notices,
+
+2. Redistributions in binary form must reproduce applicable copyright
+statements and notices, this list of conditions, and the following
+disclaimer in the documentation and/or other materials provided
+with the distribution, and
+
+3. Redistributions must contain a verbatim copy of this document.
+
+The OpenLDAP Foundation may revise this license from time to time.
+Each revision is distinguished by a version number. You may use
+this Software under terms of this license revision or under the
+terms of any subsequent revision of the license.
+
+THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
+CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
+OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+The names of the authors and copyright holders must not be used in
+advertising or otherwise to promote the sale, use or other dealing
+in this Software without specific, written prior permission. Title
+to copyright in this Software shall at all times remain with copyright
+holders.
+
+OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+
+Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
+California, USA. All Rights Reserved. Permission to copy and
+distribute verbatim copies of this document is granted.
+
+ADDITIONAL LICENSE INFORMATION:
+
+Portions Copyright (c) 1996, 1998 by Internet Software Consortium.
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+This work is based upon Base64 routines (developed by IBM) found
+Berkeley Internet Name Daemon (BIND) as distributed by ISC. They
+were adapted for inclusion in OpenLDAP Software by Kurt D. Zeilenga.
+
+>>> convertutf.c/.h from unicode, inc.-none
+
+Copyright 2001-2004 Unicode, Inc.
+
+Disclaimer
+
+This source code is provided as is by Unicode, Inc. No claims are
+made as to fitness for any particular purpose. No warranties of any
+kind are expressed or implied. The recipient agrees to determine
+applicability of information provided. If this file has been
+purchased on magnetic or optical media from Unicode, Inc., the
+sole remedy for any claim will be exchange of defective media
+within 90 days of receipt.
+
+Limitations on Rights to Redistribute This Code
+
+Unicode, Inc. hereby grants the right to freely use the information
+supplied in this file in the creation of products supporting the
+Unicode Standard, and to make copies of this file in any form
+for internal or external distribution as long as this notice
+remains attached.
+
+>>> freebsd-1.72
+
+Copyright (c) 1990, 1993 The Regents of the University of California. 3
+All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Chris Torek.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+4. Neither the name of the University nor the names of its contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+>>> icu4c-4.4.1
+
+ICU License - ICU 1.8.1 and later
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1995-2010 International Business Machines Corporation and others
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.
+
+All trademarks and registered trademarks mentioned herein are the property of their respective owners.
+
+>>> unicode-5.0
+
+Copyright (c) 2008 VMware, Inc. All rights reserved.
+
+Copyright (c) 1991-2007 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated documentation (the "Data Files") or Unicode software and any associated documentation (the "Software") to deal in the Data Files or Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Data Files or Software, and to permit persons to whom the Data Files or Software are furnished to do so, provided that (a) the above copyright notice(s) and this permission notice appear with all copies of the Data Files or Software, (b) both the above copyright notice(s) and this permission notice appear in associated documentation, and (c) there is clear notice in each modified Data File or in the Software as well as in the documentation associated with the Data File(s) or Software that the data or software has been modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder.
+
+[OPENVMTOOLS1000SS081015]
diff --git a/open-vm-tools/Makefile.am b/open-vm-tools/Makefile.am
index 8c0b3e7f..dfb7cd23 100644
--- a/open-vm-tools/Makefile.am
+++ b/open-vm-tools/Makefile.am
@@ -50,6 +50,7 @@ if HAVE_X11
endif
if HAVE_FUSE
SUBDIRS += vmblock-fuse
+ SUBDIRS += vmhgfs-fuse
endif
if !LINUX
SUBDIRS += vmblockmounter
diff --git a/open-vm-tools/Makefile.in b/open-vm-tools/Makefile.in
index c6915efc..c382a181 100644
--- a/open-vm-tools/Makefile.in
+++ b/open-vm-tools/Makefile.in
@@ -56,7 +56,7 @@ host_triplet = @host@
@ENABLE_DEPLOYPKG_TRUE@am__append_3 = libDeployPkg
@ENABLE_GRABBITMQPROXY_TRUE@am__append_4 = guestproxycerttool
@HAVE_X11_TRUE@am__append_5 = vmware-user-suid-wrapper
-@HAVE_FUSE_TRUE@am__append_6 = vmblock-fuse
+@HAVE_FUSE_TRUE@am__append_6 = vmblock-fuse vmhgfs-fuse
@LINUX_FALSE@am__append_7 = vmblockmounter
@ENABLE_TESTS_TRUE@am__append_8 = tests
@WITH_KERNEL_MODULES_TRUE@am__append_9 = modules
@@ -94,7 +94,7 @@ CTAGS = ctags
DIST_SUBDIRS = lib libvmtools libhgfs hgfsclient hgfsmounter vgauth \
checkvm libguestlib libDeployPkg rpctool guestproxycerttool \
scripts services toolbox vmware-user-suid-wrapper vmblock-fuse \
- vmblockmounter xferlogs tests modules docs
+ vmhgfs-fuse vmblockmounter xferlogs tests modules docs
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
diff --git a/open-vm-tools/NEWS b/open-vm-tools/NEWS
index 575f85c1..632fccde 100644
--- a/open-vm-tools/NEWS
+++ b/open-vm-tools/NEWS
@@ -1,3 +1,28 @@
+open-vm-tools 2015-08.28 changes:
+ * Common versioning: Infrastructure changes to enable reporting of
+ true versions for operating system specific packages. This feature
+ is dependant on host support.
+
+ * Quiesced snapshots enhancements for Linux guests running IO
+ workload: Robustness related enhancements in quiesced snapshot
+ operation. vmtoolsd service supports caching of log messages when
+ guest IO has been quiesced. Enhancements in vmbackup plugin to use
+ a separate thread to quiesce the guest OS to avoid timeout issuesxi
+ due to heavy I/O in the guest.
+
+ * Shared Folders: For Linux distributions with kernel version 4.0.0
+ and higher, there is a new FUSE based Shared Folders client which
+ is used as a replacement for the kernel mode client.
+
+ * ESXi Serviceability: Default tools logging directed to a file instead
+ of syslog or event viewer. toolbox command line interface using
+ vmware-toolbox-cmd on Linux to change tools logging levels.
+
+ * GuestInfo enhancements: Plugin enhancements to report more than 64 IP
+ addresses from the guest. These enhancements will be available only
+ after upgrading the host because the guest IP addresses limit exists
+ on host side.
+
open-vm-tools 2015.06.15 changes:
* Various compilation fixes.
diff --git a/open-vm-tools/autom4te.cache/output.0 b/open-vm-tools/autom4te.cache/output.0
index 34026def..bdab1de9 100644
--- a/open-vm-tools/autom4te.cache/output.0
+++ b/open-vm-tools/autom4te.cache/output.0
@@ -1,6 +1,6 @@
@%:@! /bin/sh
@%:@ Guess values for system-dependent variables and create Makefiles.
-@%:@ Generated by GNU Autoconf 2.61 for open-vm-tools 9.10.2.
+@%:@ Generated by GNU Autoconf 2.61 for open-vm-tools 10.0.0.
@%:@
@%:@ Report bugs to <open-vm-tools-devel@lists.sourceforge.net>.
@%:@
@@ -728,8 +728,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='open-vm-tools'
PACKAGE_TARNAME='open-vm-tools'
-PACKAGE_VERSION='9.10.2'
-PACKAGE_STRING='open-vm-tools 9.10.2'
+PACKAGE_VERSION='10.0.0'
+PACKAGE_STRING='open-vm-tools 10.0.0'
PACKAGE_BUGREPORT='open-vm-tools-devel@lists.sourceforge.net'
ac_unique_file="checkvm/checkvm.c"
@@ -1520,7 +1520,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures open-vm-tools 9.10.2 to adapt to many kinds of systems.
+\`configure' configures open-vm-tools 10.0.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1594,7 +1594,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of open-vm-tools 9.10.2:";;
+ short | recursive ) echo "Configuration of open-vm-tools 10.0.0:";;
esac
cat <<\_ACEOF
@@ -1729,7 +1729,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-open-vm-tools configure 9.10.2
+open-vm-tools configure 10.0.0
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1743,7 +1743,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by open-vm-tools $as_me 9.10.2, which was
+It was created by open-vm-tools $as_me 10.0.0, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2750,7 +2750,7 @@ fi
# Define the identity of the package.
PACKAGE='open-vm-tools'
- VERSION='9.10.2'
+ VERSION='10.0.0'
cat >>confdefs.h <<_ACEOF
@@ -24737,8 +24737,8 @@ fi
else
true
have_fuse=no;
- { echo "$as_me:$LINENO: WARNING: Fuse is missing, vmblock-fuse will be disabled." >&5
-echo "$as_me: WARNING: Fuse is missing, vmblock-fuse will be disabled." >&2;}
+ { echo "$as_me:$LINENO: WARNING: Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled." >&5
+echo "$as_me: WARNING: Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled." >&2;}
fi
@@ -35553,15 +35553,14 @@ if test "$os" = "linux"; then
LIBVMTOOLS_LIBADD="$LIBVMTOOLS_LIBADD -lrt"
- # vmhgfs is not compiled for kernels 3.17 and newer
- # Temporary short term limit until the newer kernel component is included
- if test "$osVersion" -lt 317000; then
- MODULES="$MODULES vmhgfs"
- fi
# vmxnet is not supported for kernels 3.3.0 and newer
if test "$osVersion" -lt 303000; then
MODULES="$MODULES vmxnet"
fi
+ # See if we need vmhgfs module. Starting with 4.0.0 we use FUSE
+ if test "$osVersion" -lt 400000; then
+ MODULES="$MODULES vmhgfs"
+ fi
# See if we need vmci and vsock modules. Starting with 3.9 they made
# their way into mainline kernel.
if test "$osVersion" -lt 309000; then
@@ -36088,7 +36087,7 @@ fi
###
### Create the Makefiles
###
-ac_config_files="$ac_config_files Makefile lib/Makefile lib/appUtil/Makefile lib/auth/Makefile lib/backdoor/Makefile lib/asyncsocket/Makefile lib/sslDirect/Makefile lib/pollGtk/Makefile lib/poll/Makefile lib/dataMap/Makefile lib/hashMap/Makefile lib/dict/Makefile lib/dynxdr/Makefile lib/err/Makefile lib/file/Makefile lib/foundryMsg/Makefile lib/glibUtils/Makefile lib/guestApp/Makefile lib/guestRpc/Makefile lib/hgfs/Makefile lib/hgfsBd/Makefile lib/hgfsHelper/Makefile lib/hgfsServer/Makefile lib/hgfsServerManagerGuest/Makefile lib/hgfsServerPolicyGuest/Makefile lib/impersonate/Makefile lib/lock/Makefile lib/message/Makefile lib/misc/Makefile lib/netUtil/Makefile lib/nicInfo/Makefile lib/panic/Makefile lib/panicDefault/Makefile lib/printer/Makefile lib/procMgr/Makefile lib/rpcChannel/Makefile lib/rpcIn/Makefile lib/rpcOut/Makefile lib/rpcVmx/Makefile lib/slashProc/Makefile lib/string/Makefile lib/stubs/Makefile lib/syncDriver/Makefile lib/system/Makefile lib/unicode/Makefile lib/user/Makefile lib/vmCheck/Makefile lib/vmSignal/Makefile lib/wiper/Makefile lib/xdg/Makefile services/Makefile services/vmtoolsd/Makefile services/plugins/Makefile services/plugins/desktopEvents/Makefile services/plugins/dndcp/Makefile services/plugins/grabbitmqProxy/Makefile services/plugins/guestInfo/Makefile services/plugins/hgfsServer/Makefile services/plugins/powerOps/Makefile services/plugins/resolutionSet/Makefile services/plugins/timeSync/Makefile services/plugins/vix/Makefile services/plugins/vmbackup/Makefile services/plugins/deployPkg/Makefile vmware-user-suid-wrapper/Makefile toolbox/Makefile hgfsclient/Makefile hgfsmounter/Makefile checkvm/Makefile rpctool/Makefile guestproxycerttool/Makefile vgauth/Makefile vgauth/lib/Makefile vgauth/cli/Makefile vgauth/service/Makefile libguestlib/Makefile libguestlib/vmguestlib.pc libDeployPkg/Makefile libDeployPkg/libDeployPkg.pc libhgfs/Makefile libvmtools/Makefile xferlogs/Makefile modules/Makefile vmblock-fuse/Makefile vmblockmounter/Makefile tests/Makefile tests/vmrpcdbg/Makefile tests/testDebug/Makefile tests/testPlugin/Makefile tests/testVmblock/Makefile docs/Makefile docs/api/Makefile scripts/Makefile scripts/build/rpcgen_wrapper.sh"
+ac_config_files="$ac_config_files Makefile lib/Makefile lib/appUtil/Makefile lib/auth/Makefile lib/backdoor/Makefile lib/asyncsocket/Makefile lib/sslDirect/Makefile lib/pollGtk/Makefile lib/poll/Makefile lib/dataMap/Makefile lib/hashMap/Makefile lib/dict/Makefile lib/dynxdr/Makefile lib/err/Makefile lib/file/Makefile lib/foundryMsg/Makefile lib/glibUtils/Makefile lib/guestApp/Makefile lib/guestRpc/Makefile lib/hgfs/Makefile lib/hgfsBd/Makefile lib/hgfsHelper/Makefile lib/hgfsServer/Makefile lib/hgfsServerManagerGuest/Makefile lib/hgfsServerPolicyGuest/Makefile lib/hgfsUri/Makefile lib/impersonate/Makefile lib/lock/Makefile lib/message/Makefile lib/misc/Makefile lib/netUtil/Makefile lib/nicInfo/Makefile lib/panic/Makefile lib/panicDefault/Makefile lib/procMgr/Makefile lib/rpcChannel/Makefile lib/rpcIn/Makefile lib/rpcOut/Makefile lib/rpcVmx/Makefile lib/slashProc/Makefile lib/string/Makefile lib/stubs/Makefile lib/syncDriver/Makefile lib/system/Makefile lib/unicode/Makefile lib/user/Makefile lib/vmCheck/Makefile lib/vmSignal/Makefile lib/wiper/Makefile lib/xdg/Makefile services/Makefile services/vmtoolsd/Makefile services/plugins/Makefile services/plugins/desktopEvents/Makefile services/plugins/dndcp/Makefile services/plugins/grabbitmqProxy/Makefile services/plugins/guestInfo/Makefile services/plugins/hgfsServer/Makefile services/plugins/powerOps/Makefile services/plugins/resolutionSet/Makefile services/plugins/timeSync/Makefile services/plugins/vix/Makefile services/plugins/vmbackup/Makefile services/plugins/deployPkg/Makefile vmware-user-suid-wrapper/Makefile toolbox/Makefile hgfsclient/Makefile hgfsmounter/Makefile checkvm/Makefile rpctool/Makefile guestproxycerttool/Makefile vgauth/Makefile vgauth/lib/Makefile vgauth/cli/Makefile vgauth/service/Makefile libguestlib/Makefile libguestlib/vmguestlib.pc libDeployPkg/Makefile libDeployPkg/libDeployPkg.pc libhgfs/Makefile libvmtools/Makefile xferlogs/Makefile modules/Makefile vmblock-fuse/Makefile vmhgfs-fuse/Makefile vmblockmounter/Makefile tests/Makefile tests/vmrpcdbg/Makefile tests/testDebug/Makefile tests/testPlugin/Makefile tests/testVmblock/Makefile docs/Makefile docs/api/Makefile scripts/Makefile scripts/build/rpcgen_wrapper.sh"
###
@@ -36723,7 +36722,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by open-vm-tools $as_me 9.10.2, which was
+This file was extended by open-vm-tools $as_me 10.0.0, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -36770,7 +36769,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-open-vm-tools config.status 9.10.2
+open-vm-tools config.status 10.0.0
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
@@ -36901,6 +36900,7 @@ do
"lib/hgfsServer/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServer/Makefile" ;;
"lib/hgfsServerManagerGuest/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServerManagerGuest/Makefile" ;;
"lib/hgfsServerPolicyGuest/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServerPolicyGuest/Makefile" ;;
+ "lib/hgfsUri/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsUri/Makefile" ;;
"lib/impersonate/Makefile") CONFIG_FILES="$CONFIG_FILES lib/impersonate/Makefile" ;;
"lib/lock/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lock/Makefile" ;;
"lib/message/Makefile") CONFIG_FILES="$CONFIG_FILES lib/message/Makefile" ;;
@@ -36909,7 +36909,6 @@ do
"lib/nicInfo/Makefile") CONFIG_FILES="$CONFIG_FILES lib/nicInfo/Makefile" ;;
"lib/panic/Makefile") CONFIG_FILES="$CONFIG_FILES lib/panic/Makefile" ;;
"lib/panicDefault/Makefile") CONFIG_FILES="$CONFIG_FILES lib/panicDefault/Makefile" ;;
- "lib/printer/Makefile") CONFIG_FILES="$CONFIG_FILES lib/printer/Makefile" ;;
"lib/procMgr/Makefile") CONFIG_FILES="$CONFIG_FILES lib/procMgr/Makefile" ;;
"lib/rpcChannel/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpcChannel/Makefile" ;;
"lib/rpcIn/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpcIn/Makefile" ;;
@@ -36960,6 +36959,7 @@ do
"xferlogs/Makefile") CONFIG_FILES="$CONFIG_FILES xferlogs/Makefile" ;;
"modules/Makefile") CONFIG_FILES="$CONFIG_FILES modules/Makefile" ;;
"vmblock-fuse/Makefile") CONFIG_FILES="$CONFIG_FILES vmblock-fuse/Makefile" ;;
+ "vmhgfs-fuse/Makefile") CONFIG_FILES="$CONFIG_FILES vmhgfs-fuse/Makefile" ;;
"vmblockmounter/Makefile") CONFIG_FILES="$CONFIG_FILES vmblockmounter/Makefile" ;;
"tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
"tests/vmrpcdbg/Makefile") CONFIG_FILES="$CONFIG_FILES tests/vmrpcdbg/Makefile" ;;
diff --git a/open-vm-tools/autom4te.cache/output.1 b/open-vm-tools/autom4te.cache/output.1
index fe7d0485..5d6c6796 100644
--- a/open-vm-tools/autom4te.cache/output.1
+++ b/open-vm-tools/autom4te.cache/output.1
@@ -1,6 +1,6 @@
@%:@! /bin/sh
@%:@ Guess values for system-dependent variables and create Makefiles.
-@%:@ Generated by GNU Autoconf 2.61 for open-vm-tools 9.10.2.
+@%:@ Generated by GNU Autoconf 2.61 for open-vm-tools 10.0.0.
@%:@
@%:@ Report bugs to <open-vm-tools-devel@lists.sourceforge.net>.
@%:@
@@ -723,8 +723,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='open-vm-tools'
PACKAGE_TARNAME='open-vm-tools'
-PACKAGE_VERSION='9.10.2'
-PACKAGE_STRING='open-vm-tools 9.10.2'
+PACKAGE_VERSION='10.0.0'
+PACKAGE_STRING='open-vm-tools 10.0.0'
PACKAGE_BUGREPORT='open-vm-tools-devel@lists.sourceforge.net'
ac_unique_file="checkvm/checkvm.c"
@@ -1517,7 +1517,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures open-vm-tools 9.10.2 to adapt to many kinds of systems.
+\`configure' configures open-vm-tools 10.0.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1591,7 +1591,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of open-vm-tools 9.10.2:";;
+ short | recursive ) echo "Configuration of open-vm-tools 10.0.0:";;
esac
cat <<\_ACEOF
@@ -1723,7 +1723,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-open-vm-tools configure 9.10.2
+open-vm-tools configure 10.0.0
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1737,7 +1737,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by open-vm-tools $as_me 9.10.2, which was
+It was created by open-vm-tools $as_me 10.0.0, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2744,7 +2744,7 @@ fi
# Define the identity of the package.
PACKAGE='open-vm-tools'
- VERSION='9.10.2'
+ VERSION='10.0.0'
cat >>confdefs.h <<_ACEOF
@@ -20000,8 +20000,8 @@ fi
else
true
have_fuse=no;
- { echo "$as_me:$LINENO: WARNING: Fuse is missing, vmblock-fuse will be disabled." >&5
-echo "$as_me: WARNING: Fuse is missing, vmblock-fuse will be disabled." >&2;}
+ { echo "$as_me:$LINENO: WARNING: Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled." >&5
+echo "$as_me: WARNING: Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled." >&2;}
fi
@@ -30816,15 +30816,14 @@ if test "$os" = "linux"; then
LIBVMTOOLS_LIBADD="$LIBVMTOOLS_LIBADD -lrt"
- # vmhgfs is not compiled for kernels 3.17 and newer
- # Temporary short term limit until the newer kernel component is included
- if test "$osVersion" -lt 317000; then
- MODULES="$MODULES vmhgfs"
- fi
# vmxnet is not supported for kernels 3.3.0 and newer
if test "$osVersion" -lt 303000; then
MODULES="$MODULES vmxnet"
fi
+ # See if we need vmhgfs module. Starting with 4.0.0 we use FUSE
+ if test "$osVersion" -lt 400000; then
+ MODULES="$MODULES vmhgfs"
+ fi
# See if we need vmci and vsock modules. Starting with 3.9 they made
# their way into mainline kernel.
if test "$osVersion" -lt 309000; then
@@ -31351,7 +31350,7 @@ fi
###
### Create the Makefiles
###
-ac_config_files="$ac_config_files Makefile lib/Makefile lib/appUtil/Makefile lib/auth/Makefile lib/backdoor/Makefile lib/asyncsocket/Makefile lib/sslDirect/Makefile lib/pollGtk/Makefile lib/poll/Makefile lib/dataMap/Makefile lib/hashMap/Makefile lib/dict/Makefile lib/dynxdr/Makefile lib/err/Makefile lib/file/Makefile lib/foundryMsg/Makefile lib/glibUtils/Makefile lib/guestApp/Makefile lib/guestRpc/Makefile lib/hgfs/Makefile lib/hgfsBd/Makefile lib/hgfsHelper/Makefile lib/hgfsServer/Makefile lib/hgfsServerManagerGuest/Makefile lib/hgfsServerPolicyGuest/Makefile lib/impersonate/Makefile lib/lock/Makefile lib/message/Makefile lib/misc/Makefile lib/netUtil/Makefile lib/nicInfo/Makefile lib/panic/Makefile lib/panicDefault/Makefile lib/printer/Makefile lib/procMgr/Makefile lib/rpcChannel/Makefile lib/rpcIn/Makefile lib/rpcOut/Makefile lib/rpcVmx/Makefile lib/slashProc/Makefile lib/string/Makefile lib/stubs/Makefile lib/syncDriver/Makefile lib/system/Makefile lib/unicode/Makefile lib/user/Makefile lib/vmCheck/Makefile lib/vmSignal/Makefile lib/wiper/Makefile lib/xdg/Makefile services/Makefile services/vmtoolsd/Makefile services/plugins/Makefile services/plugins/desktopEvents/Makefile services/plugins/dndcp/Makefile services/plugins/grabbitmqProxy/Makefile services/plugins/guestInfo/Makefile services/plugins/hgfsServer/Makefile services/plugins/powerOps/Makefile services/plugins/resolutionSet/Makefile services/plugins/timeSync/Makefile services/plugins/vix/Makefile services/plugins/vmbackup/Makefile services/plugins/deployPkg/Makefile vmware-user-suid-wrapper/Makefile toolbox/Makefile hgfsclient/Makefile hgfsmounter/Makefile checkvm/Makefile rpctool/Makefile guestproxycerttool/Makefile vgauth/Makefile vgauth/lib/Makefile vgauth/cli/Makefile vgauth/service/Makefile libguestlib/Makefile libguestlib/vmguestlib.pc libDeployPkg/Makefile libDeployPkg/libDeployPkg.pc libhgfs/Makefile libvmtools/Makefile xferlogs/Makefile modules/Makefile vmblock-fuse/Makefile vmblockmounter/Makefile tests/Makefile tests/vmrpcdbg/Makefile tests/testDebug/Makefile tests/testPlugin/Makefile tests/testVmblock/Makefile docs/Makefile docs/api/Makefile scripts/Makefile scripts/build/rpcgen_wrapper.sh"
+ac_config_files="$ac_config_files Makefile lib/Makefile lib/appUtil/Makefile lib/auth/Makefile lib/backdoor/Makefile lib/asyncsocket/Makefile lib/sslDirect/Makefile lib/pollGtk/Makefile lib/poll/Makefile lib/dataMap/Makefile lib/hashMap/Makefile lib/dict/Makefile lib/dynxdr/Makefile lib/err/Makefile lib/file/Makefile lib/foundryMsg/Makefile lib/glibUtils/Makefile lib/guestApp/Makefile lib/guestRpc/Makefile lib/hgfs/Makefile lib/hgfsBd/Makefile lib/hgfsHelper/Makefile lib/hgfsServer/Makefile lib/hgfsServerManagerGuest/Makefile lib/hgfsServerPolicyGuest/Makefile lib/hgfsUri/Makefile lib/impersonate/Makefile lib/lock/Makefile lib/message/Makefile lib/misc/Makefile lib/netUtil/Makefile lib/nicInfo/Makefile lib/panic/Makefile lib/panicDefault/Makefile lib/procMgr/Makefile lib/rpcChannel/Makefile lib/rpcIn/Makefile lib/rpcOut/Makefile lib/rpcVmx/Makefile lib/slashProc/Makefile lib/string/Makefile lib/stubs/Makefile lib/syncDriver/Makefile lib/system/Makefile lib/unicode/Makefile lib/user/Makefile lib/vmCheck/Makefile lib/vmSignal/Makefile lib/wiper/Makefile lib/xdg/Makefile services/Makefile services/vmtoolsd/Makefile services/plugins/Makefile services/plugins/desktopEvents/Makefile services/plugins/dndcp/Makefile services/plugins/grabbitmqProxy/Makefile services/plugins/guestInfo/Makefile services/plugins/hgfsServer/Makefile services/plugins/powerOps/Makefile services/plugins/resolutionSet/Makefile services/plugins/timeSync/Makefile services/plugins/vix/Makefile services/plugins/vmbackup/Makefile services/plugins/deployPkg/Makefile vmware-user-suid-wrapper/Makefile toolbox/Makefile hgfsclient/Makefile hgfsmounter/Makefile checkvm/Makefile rpctool/Makefile guestproxycerttool/Makefile vgauth/Makefile vgauth/lib/Makefile vgauth/cli/Makefile vgauth/service/Makefile libguestlib/Makefile libguestlib/vmguestlib.pc libDeployPkg/Makefile libDeployPkg/libDeployPkg.pc libhgfs/Makefile libvmtools/Makefile xferlogs/Makefile modules/Makefile vmblock-fuse/Makefile vmhgfs-fuse/Makefile vmblockmounter/Makefile tests/Makefile tests/vmrpcdbg/Makefile tests/testDebug/Makefile tests/testPlugin/Makefile tests/testVmblock/Makefile docs/Makefile docs/api/Makefile scripts/Makefile scripts/build/rpcgen_wrapper.sh"
###
@@ -31993,7 +31992,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by open-vm-tools $as_me 9.10.2, which was
+This file was extended by open-vm-tools $as_me 10.0.0, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -32040,7 +32039,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-open-vm-tools config.status 9.10.2
+open-vm-tools config.status 10.0.0
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
@@ -32515,6 +32514,7 @@ do
"lib/hgfsServer/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServer/Makefile" ;;
"lib/hgfsServerManagerGuest/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServerManagerGuest/Makefile" ;;
"lib/hgfsServerPolicyGuest/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServerPolicyGuest/Makefile" ;;
+ "lib/hgfsUri/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsUri/Makefile" ;;
"lib/impersonate/Makefile") CONFIG_FILES="$CONFIG_FILES lib/impersonate/Makefile" ;;
"lib/lock/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lock/Makefile" ;;
"lib/message/Makefile") CONFIG_FILES="$CONFIG_FILES lib/message/Makefile" ;;
@@ -32523,7 +32523,6 @@ do
"lib/nicInfo/Makefile") CONFIG_FILES="$CONFIG_FILES lib/nicInfo/Makefile" ;;
"lib/panic/Makefile") CONFIG_FILES="$CONFIG_FILES lib/panic/Makefile" ;;
"lib/panicDefault/Makefile") CONFIG_FILES="$CONFIG_FILES lib/panicDefault/Makefile" ;;
- "lib/printer/Makefile") CONFIG_FILES="$CONFIG_FILES lib/printer/Makefile" ;;
"lib/procMgr/Makefile") CONFIG_FILES="$CONFIG_FILES lib/procMgr/Makefile" ;;
"lib/rpcChannel/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpcChannel/Makefile" ;;
"lib/rpcIn/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpcIn/Makefile" ;;
@@ -32574,6 +32573,7 @@ do
"xferlogs/Makefile") CONFIG_FILES="$CONFIG_FILES xferlogs/Makefile" ;;
"modules/Makefile") CONFIG_FILES="$CONFIG_FILES modules/Makefile" ;;
"vmblock-fuse/Makefile") CONFIG_FILES="$CONFIG_FILES vmblock-fuse/Makefile" ;;
+ "vmhgfs-fuse/Makefile") CONFIG_FILES="$CONFIG_FILES vmhgfs-fuse/Makefile" ;;
"vmblockmounter/Makefile") CONFIG_FILES="$CONFIG_FILES vmblockmounter/Makefile" ;;
"tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
"tests/vmrpcdbg/Makefile") CONFIG_FILES="$CONFIG_FILES tests/vmrpcdbg/Makefile" ;;
diff --git a/open-vm-tools/autom4te.cache/output.2 b/open-vm-tools/autom4te.cache/output.2
index fe7d0485..5d6c6796 100644
--- a/open-vm-tools/autom4te.cache/output.2
+++ b/open-vm-tools/autom4te.cache/output.2
@@ -1,6 +1,6 @@
@%:@! /bin/sh
@%:@ Guess values for system-dependent variables and create Makefiles.
-@%:@ Generated by GNU Autoconf 2.61 for open-vm-tools 9.10.2.
+@%:@ Generated by GNU Autoconf 2.61 for open-vm-tools 10.0.0.
@%:@
@%:@ Report bugs to <open-vm-tools-devel@lists.sourceforge.net>.
@%:@
@@ -723,8 +723,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='open-vm-tools'
PACKAGE_TARNAME='open-vm-tools'
-PACKAGE_VERSION='9.10.2'
-PACKAGE_STRING='open-vm-tools 9.10.2'
+PACKAGE_VERSION='10.0.0'
+PACKAGE_STRING='open-vm-tools 10.0.0'
PACKAGE_BUGREPORT='open-vm-tools-devel@lists.sourceforge.net'
ac_unique_file="checkvm/checkvm.c"
@@ -1517,7 +1517,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures open-vm-tools 9.10.2 to adapt to many kinds of systems.
+\`configure' configures open-vm-tools 10.0.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1591,7 +1591,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of open-vm-tools 9.10.2:";;
+ short | recursive ) echo "Configuration of open-vm-tools 10.0.0:";;
esac
cat <<\_ACEOF
@@ -1723,7 +1723,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-open-vm-tools configure 9.10.2
+open-vm-tools configure 10.0.0
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1737,7 +1737,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by open-vm-tools $as_me 9.10.2, which was
+It was created by open-vm-tools $as_me 10.0.0, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2744,7 +2744,7 @@ fi
# Define the identity of the package.
PACKAGE='open-vm-tools'
- VERSION='9.10.2'
+ VERSION='10.0.0'
cat >>confdefs.h <<_ACEOF
@@ -20000,8 +20000,8 @@ fi
else
true
have_fuse=no;
- { echo "$as_me:$LINENO: WARNING: Fuse is missing, vmblock-fuse will be disabled." >&5
-echo "$as_me: WARNING: Fuse is missing, vmblock-fuse will be disabled." >&2;}
+ { echo "$as_me:$LINENO: WARNING: Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled." >&5
+echo "$as_me: WARNING: Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled." >&2;}
fi
@@ -30816,15 +30816,14 @@ if test "$os" = "linux"; then
LIBVMTOOLS_LIBADD="$LIBVMTOOLS_LIBADD -lrt"
- # vmhgfs is not compiled for kernels 3.17 and newer
- # Temporary short term limit until the newer kernel component is included
- if test "$osVersion" -lt 317000; then
- MODULES="$MODULES vmhgfs"
- fi
# vmxnet is not supported for kernels 3.3.0 and newer
if test "$osVersion" -lt 303000; then
MODULES="$MODULES vmxnet"
fi
+ # See if we need vmhgfs module. Starting with 4.0.0 we use FUSE
+ if test "$osVersion" -lt 400000; then
+ MODULES="$MODULES vmhgfs"
+ fi
# See if we need vmci and vsock modules. Starting with 3.9 they made
# their way into mainline kernel.
if test "$osVersion" -lt 309000; then
@@ -31351,7 +31350,7 @@ fi
###
### Create the Makefiles
###
-ac_config_files="$ac_config_files Makefile lib/Makefile lib/appUtil/Makefile lib/auth/Makefile lib/backdoor/Makefile lib/asyncsocket/Makefile lib/sslDirect/Makefile lib/pollGtk/Makefile lib/poll/Makefile lib/dataMap/Makefile lib/hashMap/Makefile lib/dict/Makefile lib/dynxdr/Makefile lib/err/Makefile lib/file/Makefile lib/foundryMsg/Makefile lib/glibUtils/Makefile lib/guestApp/Makefile lib/guestRpc/Makefile lib/hgfs/Makefile lib/hgfsBd/Makefile lib/hgfsHelper/Makefile lib/hgfsServer/Makefile lib/hgfsServerManagerGuest/Makefile lib/hgfsServerPolicyGuest/Makefile lib/impersonate/Makefile lib/lock/Makefile lib/message/Makefile lib/misc/Makefile lib/netUtil/Makefile lib/nicInfo/Makefile lib/panic/Makefile lib/panicDefault/Makefile lib/printer/Makefile lib/procMgr/Makefile lib/rpcChannel/Makefile lib/rpcIn/Makefile lib/rpcOut/Makefile lib/rpcVmx/Makefile lib/slashProc/Makefile lib/string/Makefile lib/stubs/Makefile lib/syncDriver/Makefile lib/system/Makefile lib/unicode/Makefile lib/user/Makefile lib/vmCheck/Makefile lib/vmSignal/Makefile lib/wiper/Makefile lib/xdg/Makefile services/Makefile services/vmtoolsd/Makefile services/plugins/Makefile services/plugins/desktopEvents/Makefile services/plugins/dndcp/Makefile services/plugins/grabbitmqProxy/Makefile services/plugins/guestInfo/Makefile services/plugins/hgfsServer/Makefile services/plugins/powerOps/Makefile services/plugins/resolutionSet/Makefile services/plugins/timeSync/Makefile services/plugins/vix/Makefile services/plugins/vmbackup/Makefile services/plugins/deployPkg/Makefile vmware-user-suid-wrapper/Makefile toolbox/Makefile hgfsclient/Makefile hgfsmounter/Makefile checkvm/Makefile rpctool/Makefile guestproxycerttool/Makefile vgauth/Makefile vgauth/lib/Makefile vgauth/cli/Makefile vgauth/service/Makefile libguestlib/Makefile libguestlib/vmguestlib.pc libDeployPkg/Makefile libDeployPkg/libDeployPkg.pc libhgfs/Makefile libvmtools/Makefile xferlogs/Makefile modules/Makefile vmblock-fuse/Makefile vmblockmounter/Makefile tests/Makefile tests/vmrpcdbg/Makefile tests/testDebug/Makefile tests/testPlugin/Makefile tests/testVmblock/Makefile docs/Makefile docs/api/Makefile scripts/Makefile scripts/build/rpcgen_wrapper.sh"
+ac_config_files="$ac_config_files Makefile lib/Makefile lib/appUtil/Makefile lib/auth/Makefile lib/backdoor/Makefile lib/asyncsocket/Makefile lib/sslDirect/Makefile lib/pollGtk/Makefile lib/poll/Makefile lib/dataMap/Makefile lib/hashMap/Makefile lib/dict/Makefile lib/dynxdr/Makefile lib/err/Makefile lib/file/Makefile lib/foundryMsg/Makefile lib/glibUtils/Makefile lib/guestApp/Makefile lib/guestRpc/Makefile lib/hgfs/Makefile lib/hgfsBd/Makefile lib/hgfsHelper/Makefile lib/hgfsServer/Makefile lib/hgfsServerManagerGuest/Makefile lib/hgfsServerPolicyGuest/Makefile lib/hgfsUri/Makefile lib/impersonate/Makefile lib/lock/Makefile lib/message/Makefile lib/misc/Makefile lib/netUtil/Makefile lib/nicInfo/Makefile lib/panic/Makefile lib/panicDefault/Makefile lib/procMgr/Makefile lib/rpcChannel/Makefile lib/rpcIn/Makefile lib/rpcOut/Makefile lib/rpcVmx/Makefile lib/slashProc/Makefile lib/string/Makefile lib/stubs/Makefile lib/syncDriver/Makefile lib/system/Makefile lib/unicode/Makefile lib/user/Makefile lib/vmCheck/Makefile lib/vmSignal/Makefile lib/wiper/Makefile lib/xdg/Makefile services/Makefile services/vmtoolsd/Makefile services/plugins/Makefile services/plugins/desktopEvents/Makefile services/plugins/dndcp/Makefile services/plugins/grabbitmqProxy/Makefile services/plugins/guestInfo/Makefile services/plugins/hgfsServer/Makefile services/plugins/powerOps/Makefile services/plugins/resolutionSet/Makefile services/plugins/timeSync/Makefile services/plugins/vix/Makefile services/plugins/vmbackup/Makefile services/plugins/deployPkg/Makefile vmware-user-suid-wrapper/Makefile toolbox/Makefile hgfsclient/Makefile hgfsmounter/Makefile checkvm/Makefile rpctool/Makefile guestproxycerttool/Makefile vgauth/Makefile vgauth/lib/Makefile vgauth/cli/Makefile vgauth/service/Makefile libguestlib/Makefile libguestlib/vmguestlib.pc libDeployPkg/Makefile libDeployPkg/libDeployPkg.pc libhgfs/Makefile libvmtools/Makefile xferlogs/Makefile modules/Makefile vmblock-fuse/Makefile vmhgfs-fuse/Makefile vmblockmounter/Makefile tests/Makefile tests/vmrpcdbg/Makefile tests/testDebug/Makefile tests/testPlugin/Makefile tests/testVmblock/Makefile docs/Makefile docs/api/Makefile scripts/Makefile scripts/build/rpcgen_wrapper.sh"
###
@@ -31993,7 +31992,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by open-vm-tools $as_me 9.10.2, which was
+This file was extended by open-vm-tools $as_me 10.0.0, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -32040,7 +32039,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-open-vm-tools config.status 9.10.2
+open-vm-tools config.status 10.0.0
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
@@ -32515,6 +32514,7 @@ do
"lib/hgfsServer/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServer/Makefile" ;;
"lib/hgfsServerManagerGuest/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServerManagerGuest/Makefile" ;;
"lib/hgfsServerPolicyGuest/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServerPolicyGuest/Makefile" ;;
+ "lib/hgfsUri/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsUri/Makefile" ;;
"lib/impersonate/Makefile") CONFIG_FILES="$CONFIG_FILES lib/impersonate/Makefile" ;;
"lib/lock/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lock/Makefile" ;;
"lib/message/Makefile") CONFIG_FILES="$CONFIG_FILES lib/message/Makefile" ;;
@@ -32523,7 +32523,6 @@ do
"lib/nicInfo/Makefile") CONFIG_FILES="$CONFIG_FILES lib/nicInfo/Makefile" ;;
"lib/panic/Makefile") CONFIG_FILES="$CONFIG_FILES lib/panic/Makefile" ;;
"lib/panicDefault/Makefile") CONFIG_FILES="$CONFIG_FILES lib/panicDefault/Makefile" ;;
- "lib/printer/Makefile") CONFIG_FILES="$CONFIG_FILES lib/printer/Makefile" ;;
"lib/procMgr/Makefile") CONFIG_FILES="$CONFIG_FILES lib/procMgr/Makefile" ;;
"lib/rpcChannel/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpcChannel/Makefile" ;;
"lib/rpcIn/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpcIn/Makefile" ;;
@@ -32574,6 +32573,7 @@ do
"xferlogs/Makefile") CONFIG_FILES="$CONFIG_FILES xferlogs/Makefile" ;;
"modules/Makefile") CONFIG_FILES="$CONFIG_FILES modules/Makefile" ;;
"vmblock-fuse/Makefile") CONFIG_FILES="$CONFIG_FILES vmblock-fuse/Makefile" ;;
+ "vmhgfs-fuse/Makefile") CONFIG_FILES="$CONFIG_FILES vmhgfs-fuse/Makefile" ;;
"vmblockmounter/Makefile") CONFIG_FILES="$CONFIG_FILES vmblockmounter/Makefile" ;;
"tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
"tests/vmrpcdbg/Makefile") CONFIG_FILES="$CONFIG_FILES tests/vmrpcdbg/Makefile" ;;
diff --git a/open-vm-tools/autom4te.cache/traces.0 b/open-vm-tools/autom4te.cache/traces.0
index 055031ea..3ec264e9 100644
--- a/open-vm-tools/autom4te.cache/traces.0
+++ b/open-vm-tools/autom4te.cache/traces.0
@@ -9313,7 +9313,7 @@ m4trace:configure.ac:350: -1- m4_pattern_allow([^GTHREAD_CPPFLAGS$])
m4trace:configure.ac:350: -1- m4_pattern_allow([^GTHREAD_LIBS$])
m4trace:configure.ac:359: -1- m4_pattern_allow([^have_genmarshal$])
m4trace:configure.ac:371: -1- AC_VMW_CHECK_LIB([fuse], [FUSE], [fuse], [], [], [fuse.h], [fuse_main], [have_fuse=yes], [have_fuse=no;
- AC_MSG_WARN([Fuse is missing, vmblock-fuse will be disabled.])])
+ AC_MSG_WARN([Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled.])])
m4trace:configure.ac:371: -1- m4_pattern_allow([^ac_vmw_lib_cfg$])
m4trace:configure.ac:371: -1- m4_pattern_allow([^FUSE_CPPFLAGS$])
m4trace:configure.ac:371: -1- m4_pattern_allow([^FUSE_LIBS$])
@@ -9428,165 +9428,165 @@ m4trace:configure.ac:1011: -1- m4_pattern_allow([^DOT$])
m4trace:configure.ac:1012: -1- m4_pattern_allow([^HAVE_DOT$])
m4trace:configure.ac:1014: -1- m4_pattern_allow([^MSCGEN$])
m4trace:configure.ac:1022: -1- m4_pattern_allow([^MSCGEN_DIR$])
-m4trace:configure.ac:1133: -1- AM_CONDITIONAL([BUILD_HGFSMOUNTER], [test "$buildHgfsmounter" = "yes"])
-m4trace:configure.ac:1133: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_TRUE$])
-m4trace:configure.ac:1133: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_FALSE$])
-m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_TRUE])
-m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_FALSE])
-m4trace:configure.ac:1134: -1- AM_CONDITIONAL([LINUX], [test "$os" = "linux"])
-m4trace:configure.ac:1134: -1- m4_pattern_allow([^LINUX_TRUE$])
-m4trace:configure.ac:1134: -1- m4_pattern_allow([^LINUX_FALSE$])
-m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([LINUX_TRUE])
-m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([LINUX_FALSE])
-m4trace:configure.ac:1135: -1- AM_CONDITIONAL([SOLARIS], [test "$os" = "solaris"])
-m4trace:configure.ac:1135: -1- m4_pattern_allow([^SOLARIS_TRUE$])
-m4trace:configure.ac:1135: -1- m4_pattern_allow([^SOLARIS_FALSE$])
-m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([SOLARIS_TRUE])
-m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([SOLARIS_FALSE])
-m4trace:configure.ac:1136: -1- AM_CONDITIONAL([FREEBSD], [test "$os" = "freebsd" -o "$os" = "kfreebsd-gnu"])
-m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_TRUE$])
-m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_FALSE$])
-m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_TRUE])
-m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_FALSE])
-m4trace:configure.ac:1137: -1- AM_CONDITIONAL([FREEBSD_CUSTOM_SYSDIR], [test \( "$os" = "freebsd" -o "$os" = "kfreebsd-gnu" \) -a -n "$SYSDIR"])
-m4trace:configure.ac:1137: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_TRUE$])
-m4trace:configure.ac:1137: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_FALSE$])
-m4trace:configure.ac:1137: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_TRUE])
-m4trace:configure.ac:1137: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_FALSE])
-m4trace:configure.ac:1139: -1- AM_CONDITIONAL([THIRTY_TWO_BIT_USERSPACE], [test "$userSpaceBitness" = "32"])
-m4trace:configure.ac:1139: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_TRUE$])
-m4trace:configure.ac:1139: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_FALSE$])
-m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_TRUE])
-m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_FALSE])
-m4trace:configure.ac:1140: -1- AM_CONDITIONAL([HAVE_X11], [test "$have_x" = "yes"])
-m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_X11_TRUE$])
-m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_X11_FALSE$])
-m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_X11_TRUE])
-m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_X11_FALSE])
-m4trace:configure.ac:1141: -1- AM_CONDITIONAL([HAVE_ICU], [test "$with_icu" = "yes"])
-m4trace:configure.ac:1141: -1- m4_pattern_allow([^HAVE_ICU_TRUE$])
-m4trace:configure.ac:1141: -1- m4_pattern_allow([^HAVE_ICU_FALSE$])
-m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_TRUE])
-m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_FALSE])
-m4trace:configure.ac:1142: -1- AM_CONDITIONAL([WITH_KERNEL_MODULES], [test "$with_kernel_modules" = "yes"])
-m4trace:configure.ac:1142: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_TRUE$])
-m4trace:configure.ac:1142: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_FALSE$])
-m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_TRUE])
-m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_FALSE])
-m4trace:configure.ac:1143: -1- AM_CONDITIONAL([HAVE_XSM], [test "$have_xsm" = "yes"])
-m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XSM_TRUE$])
-m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XSM_FALSE$])
-m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_TRUE])
-m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_FALSE])
-m4trace:configure.ac:1144: -1- AM_CONDITIONAL([HAVE_XCOMPOSITE], [test "$have_xcomposite" = "yes"])
-m4trace:configure.ac:1144: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_TRUE$])
-m4trace:configure.ac:1144: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_FALSE$])
-m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_TRUE])
-m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_FALSE])
-m4trace:configure.ac:1145: -1- AM_CONDITIONAL([ENABLE_TESTS], [test "$have_cunit" = "yes"])
-m4trace:configure.ac:1145: -1- m4_pattern_allow([^ENABLE_TESTS_TRUE$])
-m4trace:configure.ac:1145: -1- m4_pattern_allow([^ENABLE_TESTS_FALSE$])
-m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_TRUE])
-m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_FALSE])
-m4trace:configure.ac:1146: -1- AM_CONDITIONAL([WITH_ROOT_PRIVILEGES], [test "$with_root_privileges" = "yes"])
-m4trace:configure.ac:1146: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_TRUE$])
-m4trace:configure.ac:1146: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_FALSE$])
-m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_TRUE])
-m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_FALSE])
-m4trace:configure.ac:1147: -1- AM_CONDITIONAL([HAVE_DNET], [test "$have_dnet" = "yes"])
-m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DNET_TRUE$])
-m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DNET_FALSE$])
-m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_TRUE])
-m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_FALSE])
-m4trace:configure.ac:1148: -1- AM_CONDITIONAL([HAVE_DOXYGEN], [test "$have_doxygen" = "yes"])
-m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_DOXYGEN_TRUE$])
-m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_DOXYGEN_FALSE$])
-m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_TRUE])
-m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_FALSE])
-m4trace:configure.ac:1149: -1- AM_CONDITIONAL([HAVE_FUSE], [test "$have_fuse" = "yes"])
-m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_FUSE_TRUE$])
-m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_FUSE_FALSE$])
-m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_TRUE])
-m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_FALSE])
-m4trace:configure.ac:1150: -1- AM_CONDITIONAL([HAVE_GNU_LD], [test "$with_gnu_ld" = "yes"])
-m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GNU_LD_TRUE$])
-m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GNU_LD_FALSE$])
-m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_TRUE])
-m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_FALSE])
-m4trace:configure.ac:1151: -1- AM_CONDITIONAL([HAVE_GTKMM], [test "$have_x" = "yes" -a "$with_gtkmm" = "yes"])
-m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_GTKMM_TRUE$])
-m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_GTKMM_FALSE$])
-m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_TRUE])
-m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_FALSE])
-m4trace:configure.ac:1152: -1- AM_CONDITIONAL([HAVE_PAM], [test "$with_pam" = "yes"])
-m4trace:configure.ac:1152: -1- m4_pattern_allow([^HAVE_PAM_TRUE$])
-m4trace:configure.ac:1152: -1- m4_pattern_allow([^HAVE_PAM_FALSE$])
-m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_TRUE])
-m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_FALSE])
-m4trace:configure.ac:1153: -1- AM_CONDITIONAL([USE_SLASH_PROC], [test "$os" = "linux"])
-m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_SLASH_PROC_TRUE$])
-m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_SLASH_PROC_FALSE$])
-m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_TRUE])
-m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_FALSE])
-m4trace:configure.ac:1154: -1- AM_CONDITIONAL([USE_PRINTF_WRAPPERS], [test "$bsdPrintfWrappers" = "yes"])
-m4trace:configure.ac:1154: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_TRUE$])
-m4trace:configure.ac:1154: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_FALSE$])
-m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_TRUE])
-m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_FALSE])
-m4trace:configure.ac:1155: -1- AM_CONDITIONAL([ENABLE_DEPLOYPKG], [test "$enable_deploypkg" = "yes"])
-m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_TRUE$])
-m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_FALSE$])
-m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_TRUE])
-m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_FALSE])
-m4trace:configure.ac:1156: -1- AM_CONDITIONAL([ENABLE_GRABBITMQPROXY], [test "$enable_grabbitmqproxy" = "yes"])
-m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_TRUE$])
-m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_FALSE$])
-m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_TRUE])
-m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_FALSE])
-m4trace:configure.ac:1157: -1- AM_CONDITIONAL([ENABLE_VGAUTH], [test "$enable_vgauth" = "yes"])
-m4trace:configure.ac:1157: -1- m4_pattern_allow([^ENABLE_VGAUTH_TRUE$])
-m4trace:configure.ac:1157: -1- m4_pattern_allow([^ENABLE_VGAUTH_FALSE$])
-m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_TRUE])
-m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_FALSE])
-m4trace:configure.ac:1158: -1- AM_CONDITIONAL([HAVE_VSOCK], [test "$os" = "linux"])
-m4trace:configure.ac:1158: -1- m4_pattern_allow([^HAVE_VSOCK_TRUE$])
-m4trace:configure.ac:1158: -1- m4_pattern_allow([^HAVE_VSOCK_FALSE$])
-m4trace:configure.ac:1158: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_TRUE])
-m4trace:configure.ac:1158: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_FALSE])
-m4trace:configure.ac:1161: -1- m4_pattern_allow([^NO_XSM$])
-m4trace:configure.ac:1165: -1- m4_pattern_allow([^NO_XCOMPOSITE$])
-m4trace:configure.ac:1177: -1- m4_pattern_allow([^NO_MULTIMON$])
-m4trace:configure.ac:1219: -1- m4_pattern_allow([^HGFS_LIBS$])
-m4trace:configure.ac:1220: -1- m4_pattern_allow([^TOOLS_VERSION$])
-m4trace:configure.ac:1221: -1- m4_pattern_allow([^TARGET_OS$])
-m4trace:configure.ac:1222: -1- m4_pattern_allow([^KERNEL_RELEASE$])
-m4trace:configure.ac:1223: -1- m4_pattern_allow([^LINUXINCLUDE$])
-m4trace:configure.ac:1224: -1- m4_pattern_allow([^MODULES_OS$])
-m4trace:configure.ac:1225: -1- m4_pattern_allow([^MODULES_DIR$])
-m4trace:configure.ac:1226: -1- m4_pattern_allow([^MODULES$])
-m4trace:configure.ac:1227: -1- m4_pattern_allow([^COMMON_XLIBS$])
-m4trace:configure.ac:1228: -1- m4_pattern_allow([^XSM_LIBS$])
-m4trace:configure.ac:1229: -1- m4_pattern_allow([^XCOMPOSITE_LIBS$])
-m4trace:configure.ac:1230: -1- m4_pattern_allow([^PAM_PREFIX$])
-m4trace:configure.ac:1231: -1- m4_pattern_allow([^PLUGIN_CPPFLAGS$])
-m4trace:configure.ac:1232: -1- m4_pattern_allow([^PLUGIN_LDFLAGS$])
-m4trace:configure.ac:1233: -1- m4_pattern_allow([^VMTOOLS_CPPFLAGS$])
-m4trace:configure.ac:1234: -1- m4_pattern_allow([^VMTOOLS_LIBS$])
-m4trace:configure.ac:1235: -1- m4_pattern_allow([^RPCGENFLAGS$])
-m4trace:configure.ac:1236: -1- m4_pattern_allow([^XDR_LIBS$])
-m4trace:configure.ac:1237: -1- m4_pattern_allow([^TEST_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1238: -1- m4_pattern_allow([^COMMON_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1239: -1- m4_pattern_allow([^VMSVC_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1240: -1- m4_pattern_allow([^VMUSR_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1245: -1- m4_pattern_allow([^SYSDIR$])
-m4trace:configure.ac:1247: -1- m4_pattern_allow([^INSTVMSG$])
-m4trace:configure.ac:1248: -1- m4_pattern_allow([^RPCGEN_WRAPPER$])
-m4trace:configure.ac:1252: -1- m4_pattern_allow([^LIB_AUTH_CPPFLAGS$])
-m4trace:configure.ac:1253: -1- m4_pattern_allow([^LIB_IMPERSONATE_CPPFLAGS$])
-m4trace:configure.ac:1254: -1- m4_pattern_allow([^LIB_USER_CPPFLAGS$])
-m4trace:configure.ac:1255: -1- m4_pattern_allow([^LIBVMTOOLS_LIBADD$])
-m4trace:configure.ac:1259: -1- m4_pattern_allow([^VIX_LIBADD$])
-m4trace:configure.ac:1260: -1- m4_pattern_allow([^VGAUTH_LIBADD$])
+m4trace:configure.ac:1132: -1- AM_CONDITIONAL([BUILD_HGFSMOUNTER], [test "$buildHgfsmounter" = "yes"])
+m4trace:configure.ac:1132: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_TRUE$])
+m4trace:configure.ac:1132: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_FALSE$])
+m4trace:configure.ac:1132: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_TRUE])
+m4trace:configure.ac:1132: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_FALSE])
+m4trace:configure.ac:1133: -1- AM_CONDITIONAL([LINUX], [test "$os" = "linux"])
+m4trace:configure.ac:1133: -1- m4_pattern_allow([^LINUX_TRUE$])
+m4trace:configure.ac:1133: -1- m4_pattern_allow([^LINUX_FALSE$])
+m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([LINUX_TRUE])
+m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([LINUX_FALSE])
+m4trace:configure.ac:1134: -1- AM_CONDITIONAL([SOLARIS], [test "$os" = "solaris"])
+m4trace:configure.ac:1134: -1- m4_pattern_allow([^SOLARIS_TRUE$])
+m4trace:configure.ac:1134: -1- m4_pattern_allow([^SOLARIS_FALSE$])
+m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([SOLARIS_TRUE])
+m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([SOLARIS_FALSE])
+m4trace:configure.ac:1135: -1- AM_CONDITIONAL([FREEBSD], [test "$os" = "freebsd" -o "$os" = "kfreebsd-gnu"])
+m4trace:configure.ac:1135: -1- m4_pattern_allow([^FREEBSD_TRUE$])
+m4trace:configure.ac:1135: -1- m4_pattern_allow([^FREEBSD_FALSE$])
+m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([FREEBSD_TRUE])
+m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([FREEBSD_FALSE])
+m4trace:configure.ac:1136: -1- AM_CONDITIONAL([FREEBSD_CUSTOM_SYSDIR], [test \( "$os" = "freebsd" -o "$os" = "kfreebsd-gnu" \) -a -n "$SYSDIR"])
+m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_TRUE$])
+m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_FALSE$])
+m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_TRUE])
+m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_FALSE])
+m4trace:configure.ac:1138: -1- AM_CONDITIONAL([THIRTY_TWO_BIT_USERSPACE], [test "$userSpaceBitness" = "32"])
+m4trace:configure.ac:1138: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_TRUE$])
+m4trace:configure.ac:1138: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_FALSE$])
+m4trace:configure.ac:1138: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_TRUE])
+m4trace:configure.ac:1138: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_FALSE])
+m4trace:configure.ac:1139: -1- AM_CONDITIONAL([HAVE_X11], [test "$have_x" = "yes"])
+m4trace:configure.ac:1139: -1- m4_pattern_allow([^HAVE_X11_TRUE$])
+m4trace:configure.ac:1139: -1- m4_pattern_allow([^HAVE_X11_FALSE$])
+m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([HAVE_X11_TRUE])
+m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([HAVE_X11_FALSE])
+m4trace:configure.ac:1140: -1- AM_CONDITIONAL([HAVE_ICU], [test "$with_icu" = "yes"])
+m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_ICU_TRUE$])
+m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_ICU_FALSE$])
+m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_TRUE])
+m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_FALSE])
+m4trace:configure.ac:1141: -1- AM_CONDITIONAL([WITH_KERNEL_MODULES], [test "$with_kernel_modules" = "yes"])
+m4trace:configure.ac:1141: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_TRUE$])
+m4trace:configure.ac:1141: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_FALSE$])
+m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_TRUE])
+m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_FALSE])
+m4trace:configure.ac:1142: -1- AM_CONDITIONAL([HAVE_XSM], [test "$have_xsm" = "yes"])
+m4trace:configure.ac:1142: -1- m4_pattern_allow([^HAVE_XSM_TRUE$])
+m4trace:configure.ac:1142: -1- m4_pattern_allow([^HAVE_XSM_FALSE$])
+m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_TRUE])
+m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_FALSE])
+m4trace:configure.ac:1143: -1- AM_CONDITIONAL([HAVE_XCOMPOSITE], [test "$have_xcomposite" = "yes"])
+m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_TRUE$])
+m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_FALSE$])
+m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_TRUE])
+m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_FALSE])
+m4trace:configure.ac:1144: -1- AM_CONDITIONAL([ENABLE_TESTS], [test "$have_cunit" = "yes"])
+m4trace:configure.ac:1144: -1- m4_pattern_allow([^ENABLE_TESTS_TRUE$])
+m4trace:configure.ac:1144: -1- m4_pattern_allow([^ENABLE_TESTS_FALSE$])
+m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_TRUE])
+m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_FALSE])
+m4trace:configure.ac:1145: -1- AM_CONDITIONAL([WITH_ROOT_PRIVILEGES], [test "$with_root_privileges" = "yes"])
+m4trace:configure.ac:1145: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_TRUE$])
+m4trace:configure.ac:1145: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_FALSE$])
+m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_TRUE])
+m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_FALSE])
+m4trace:configure.ac:1146: -1- AM_CONDITIONAL([HAVE_DNET], [test "$have_dnet" = "yes"])
+m4trace:configure.ac:1146: -1- m4_pattern_allow([^HAVE_DNET_TRUE$])
+m4trace:configure.ac:1146: -1- m4_pattern_allow([^HAVE_DNET_FALSE$])
+m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_TRUE])
+m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_FALSE])
+m4trace:configure.ac:1147: -1- AM_CONDITIONAL([HAVE_DOXYGEN], [test "$have_doxygen" = "yes"])
+m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DOXYGEN_TRUE$])
+m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DOXYGEN_FALSE$])
+m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_TRUE])
+m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_FALSE])
+m4trace:configure.ac:1148: -1- AM_CONDITIONAL([HAVE_FUSE], [test "$have_fuse" = "yes"])
+m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_FUSE_TRUE$])
+m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_FUSE_FALSE$])
+m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_TRUE])
+m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_FALSE])
+m4trace:configure.ac:1149: -1- AM_CONDITIONAL([HAVE_GNU_LD], [test "$with_gnu_ld" = "yes"])
+m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_GNU_LD_TRUE$])
+m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_GNU_LD_FALSE$])
+m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_TRUE])
+m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_FALSE])
+m4trace:configure.ac:1150: -1- AM_CONDITIONAL([HAVE_GTKMM], [test "$have_x" = "yes" -a "$with_gtkmm" = "yes"])
+m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GTKMM_TRUE$])
+m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GTKMM_FALSE$])
+m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_TRUE])
+m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_FALSE])
+m4trace:configure.ac:1151: -1- AM_CONDITIONAL([HAVE_PAM], [test "$with_pam" = "yes"])
+m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_PAM_TRUE$])
+m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_PAM_FALSE$])
+m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_TRUE])
+m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_FALSE])
+m4trace:configure.ac:1152: -1- AM_CONDITIONAL([USE_SLASH_PROC], [test "$os" = "linux"])
+m4trace:configure.ac:1152: -1- m4_pattern_allow([^USE_SLASH_PROC_TRUE$])
+m4trace:configure.ac:1152: -1- m4_pattern_allow([^USE_SLASH_PROC_FALSE$])
+m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_TRUE])
+m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_FALSE])
+m4trace:configure.ac:1153: -1- AM_CONDITIONAL([USE_PRINTF_WRAPPERS], [test "$bsdPrintfWrappers" = "yes"])
+m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_TRUE$])
+m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_FALSE$])
+m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_TRUE])
+m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_FALSE])
+m4trace:configure.ac:1154: -1- AM_CONDITIONAL([ENABLE_DEPLOYPKG], [test "$enable_deploypkg" = "yes"])
+m4trace:configure.ac:1154: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_TRUE$])
+m4trace:configure.ac:1154: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_FALSE$])
+m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_TRUE])
+m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_FALSE])
+m4trace:configure.ac:1155: -1- AM_CONDITIONAL([ENABLE_GRABBITMQPROXY], [test "$enable_grabbitmqproxy" = "yes"])
+m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_TRUE$])
+m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_FALSE$])
+m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_TRUE])
+m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_FALSE])
+m4trace:configure.ac:1156: -1- AM_CONDITIONAL([ENABLE_VGAUTH], [test "$enable_vgauth" = "yes"])
+m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_VGAUTH_TRUE$])
+m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_VGAUTH_FALSE$])
+m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_TRUE])
+m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_FALSE])
+m4trace:configure.ac:1157: -1- AM_CONDITIONAL([HAVE_VSOCK], [test "$os" = "linux"])
+m4trace:configure.ac:1157: -1- m4_pattern_allow([^HAVE_VSOCK_TRUE$])
+m4trace:configure.ac:1157: -1- m4_pattern_allow([^HAVE_VSOCK_FALSE$])
+m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_TRUE])
+m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_FALSE])
+m4trace:configure.ac:1160: -1- m4_pattern_allow([^NO_XSM$])
+m4trace:configure.ac:1164: -1- m4_pattern_allow([^NO_XCOMPOSITE$])
+m4trace:configure.ac:1176: -1- m4_pattern_allow([^NO_MULTIMON$])
+m4trace:configure.ac:1218: -1- m4_pattern_allow([^HGFS_LIBS$])
+m4trace:configure.ac:1219: -1- m4_pattern_allow([^TOOLS_VERSION$])
+m4trace:configure.ac:1220: -1- m4_pattern_allow([^TARGET_OS$])
+m4trace:configure.ac:1221: -1- m4_pattern_allow([^KERNEL_RELEASE$])
+m4trace:configure.ac:1222: -1- m4_pattern_allow([^LINUXINCLUDE$])
+m4trace:configure.ac:1223: -1- m4_pattern_allow([^MODULES_OS$])
+m4trace:configure.ac:1224: -1- m4_pattern_allow([^MODULES_DIR$])
+m4trace:configure.ac:1225: -1- m4_pattern_allow([^MODULES$])
+m4trace:configure.ac:1226: -1- m4_pattern_allow([^COMMON_XLIBS$])
+m4trace:configure.ac:1227: -1- m4_pattern_allow([^XSM_LIBS$])
+m4trace:configure.ac:1228: -1- m4_pattern_allow([^XCOMPOSITE_LIBS$])
+m4trace:configure.ac:1229: -1- m4_pattern_allow([^PAM_PREFIX$])
+m4trace:configure.ac:1230: -1- m4_pattern_allow([^PLUGIN_CPPFLAGS$])
+m4trace:configure.ac:1231: -1- m4_pattern_allow([^PLUGIN_LDFLAGS$])
+m4trace:configure.ac:1232: -1- m4_pattern_allow([^VMTOOLS_CPPFLAGS$])
+m4trace:configure.ac:1233: -1- m4_pattern_allow([^VMTOOLS_LIBS$])
+m4trace:configure.ac:1234: -1- m4_pattern_allow([^RPCGENFLAGS$])
+m4trace:configure.ac:1235: -1- m4_pattern_allow([^XDR_LIBS$])
+m4trace:configure.ac:1236: -1- m4_pattern_allow([^TEST_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1237: -1- m4_pattern_allow([^COMMON_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1238: -1- m4_pattern_allow([^VMSVC_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1239: -1- m4_pattern_allow([^VMUSR_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1244: -1- m4_pattern_allow([^SYSDIR$])
+m4trace:configure.ac:1246: -1- m4_pattern_allow([^INSTVMSG$])
+m4trace:configure.ac:1247: -1- m4_pattern_allow([^RPCGEN_WRAPPER$])
+m4trace:configure.ac:1251: -1- m4_pattern_allow([^LIB_AUTH_CPPFLAGS$])
+m4trace:configure.ac:1252: -1- m4_pattern_allow([^LIB_IMPERSONATE_CPPFLAGS$])
+m4trace:configure.ac:1253: -1- m4_pattern_allow([^LIB_USER_CPPFLAGS$])
+m4trace:configure.ac:1254: -1- m4_pattern_allow([^LIBVMTOOLS_LIBADD$])
+m4trace:configure.ac:1258: -1- m4_pattern_allow([^VIX_LIBADD$])
+m4trace:configure.ac:1259: -1- m4_pattern_allow([^VGAUTH_LIBADD$])
m4trace:configure.ac:1365: -1- m4_pattern_allow([^LIB@&t@OBJS$])
m4trace:configure.ac:1365: -1- m4_pattern_allow([^LTLIBOBJS$])
m4trace:configure.ac:1365: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS
diff --git a/open-vm-tools/autom4te.cache/traces.1 b/open-vm-tools/autom4te.cache/traces.1
index 0620b3bb..6e457618 100644
--- a/open-vm-tools/autom4te.cache/traces.1
+++ b/open-vm-tools/autom4te.cache/traces.1
@@ -4,7 +4,7 @@ m4trace:aclocal.m4:899: -1- m4_include([m4/ltsugar.m4])
m4trace:aclocal.m4:900: -1- m4_include([m4/ltversion.m4])
m4trace:aclocal.m4:901: -1- m4_include([m4/lt~obsolete.m4])
m4trace:aclocal.m4:902: -1- m4_include([m4/vmtools.m4])
-m4trace:configure.ac:43: -1- AC_INIT([open-vm-tools], [9.10.2], [open-vm-tools-devel@lists.sourceforge.net])
+m4trace:configure.ac:43: -1- AC_INIT([open-vm-tools], [10.0.0], [open-vm-tools-devel@lists.sourceforge.net])
m4trace:configure.ac:43: -1- m4_pattern_forbid([^_?A[CHUM]_])
m4trace:configure.ac:43: -1- m4_pattern_forbid([_AC_])
m4trace:configure.ac:43: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS'])
@@ -970,333 +970,333 @@ m4trace:configure.ac:1014: -1- m4_pattern_allow([^MSCGEN$])
m4trace:configure.ac:1022: -1- AC_SUBST([MSCGEN_DIR])
m4trace:configure.ac:1022: -1- AC_SUBST_TRACE([MSCGEN_DIR])
m4trace:configure.ac:1022: -1- m4_pattern_allow([^MSCGEN_DIR$])
-m4trace:configure.ac:1133: -1- AM_CONDITIONAL([BUILD_HGFSMOUNTER], [test "$buildHgfsmounter" = "yes"])
-m4trace:configure.ac:1133: -1- AC_SUBST([BUILD_HGFSMOUNTER_TRUE])
-m4trace:configure.ac:1133: -1- AC_SUBST_TRACE([BUILD_HGFSMOUNTER_TRUE])
-m4trace:configure.ac:1133: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_TRUE$])
-m4trace:configure.ac:1133: -1- AC_SUBST([BUILD_HGFSMOUNTER_FALSE])
-m4trace:configure.ac:1133: -1- AC_SUBST_TRACE([BUILD_HGFSMOUNTER_FALSE])
-m4trace:configure.ac:1133: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_FALSE$])
-m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_TRUE])
-m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_FALSE])
-m4trace:configure.ac:1134: -1- AM_CONDITIONAL([LINUX], [test "$os" = "linux"])
-m4trace:configure.ac:1134: -1- AC_SUBST([LINUX_TRUE])
-m4trace:configure.ac:1134: -1- AC_SUBST_TRACE([LINUX_TRUE])
-m4trace:configure.ac:1134: -1- m4_pattern_allow([^LINUX_TRUE$])
-m4trace:configure.ac:1134: -1- AC_SUBST([LINUX_FALSE])
-m4trace:configure.ac:1134: -1- AC_SUBST_TRACE([LINUX_FALSE])
-m4trace:configure.ac:1134: -1- m4_pattern_allow([^LINUX_FALSE$])
-m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([LINUX_TRUE])
-m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([LINUX_FALSE])
-m4trace:configure.ac:1135: -1- AM_CONDITIONAL([SOLARIS], [test "$os" = "solaris"])
-m4trace:configure.ac:1135: -1- AC_SUBST([SOLARIS_TRUE])
-m4trace:configure.ac:1135: -1- AC_SUBST_TRACE([SOLARIS_TRUE])
-m4trace:configure.ac:1135: -1- m4_pattern_allow([^SOLARIS_TRUE$])
-m4trace:configure.ac:1135: -1- AC_SUBST([SOLARIS_FALSE])
-m4trace:configure.ac:1135: -1- AC_SUBST_TRACE([SOLARIS_FALSE])
-m4trace:configure.ac:1135: -1- m4_pattern_allow([^SOLARIS_FALSE$])
-m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([SOLARIS_TRUE])
-m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([SOLARIS_FALSE])
-m4trace:configure.ac:1136: -1- AM_CONDITIONAL([FREEBSD], [test "$os" = "freebsd" -o "$os" = "kfreebsd-gnu"])
-m4trace:configure.ac:1136: -1- AC_SUBST([FREEBSD_TRUE])
-m4trace:configure.ac:1136: -1- AC_SUBST_TRACE([FREEBSD_TRUE])
-m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_TRUE$])
-m4trace:configure.ac:1136: -1- AC_SUBST([FREEBSD_FALSE])
-m4trace:configure.ac:1136: -1- AC_SUBST_TRACE([FREEBSD_FALSE])
-m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_FALSE$])
-m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_TRUE])
-m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_FALSE])
-m4trace:configure.ac:1137: -1- AM_CONDITIONAL([FREEBSD_CUSTOM_SYSDIR], [test \( "$os" = "freebsd" -o "$os" = "kfreebsd-gnu" \) -a -n "$SYSDIR"])
-m4trace:configure.ac:1137: -1- AC_SUBST([FREEBSD_CUSTOM_SYSDIR_TRUE])
-m4trace:configure.ac:1137: -1- AC_SUBST_TRACE([FREEBSD_CUSTOM_SYSDIR_TRUE])
-m4trace:configure.ac:1137: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_TRUE$])
-m4trace:configure.ac:1137: -1- AC_SUBST([FREEBSD_CUSTOM_SYSDIR_FALSE])
-m4trace:configure.ac:1137: -1- AC_SUBST_TRACE([FREEBSD_CUSTOM_SYSDIR_FALSE])
-m4trace:configure.ac:1137: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_FALSE$])
-m4trace:configure.ac:1137: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_TRUE])
-m4trace:configure.ac:1137: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_FALSE])
-m4trace:configure.ac:1139: -1- AM_CONDITIONAL([THIRTY_TWO_BIT_USERSPACE], [test "$userSpaceBitness" = "32"])
-m4trace:configure.ac:1139: -1- AC_SUBST([THIRTY_TWO_BIT_USERSPACE_TRUE])
-m4trace:configure.ac:1139: -1- AC_SUBST_TRACE([THIRTY_TWO_BIT_USERSPACE_TRUE])
-m4trace:configure.ac:1139: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_TRUE$])
-m4trace:configure.ac:1139: -1- AC_SUBST([THIRTY_TWO_BIT_USERSPACE_FALSE])
-m4trace:configure.ac:1139: -1- AC_SUBST_TRACE([THIRTY_TWO_BIT_USERSPACE_FALSE])
-m4trace:configure.ac:1139: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_FALSE$])
-m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_TRUE])
-m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_FALSE])
-m4trace:configure.ac:1140: -1- AM_CONDITIONAL([HAVE_X11], [test "$have_x" = "yes"])
-m4trace:configure.ac:1140: -1- AC_SUBST([HAVE_X11_TRUE])
-m4trace:configure.ac:1140: -1- AC_SUBST_TRACE([HAVE_X11_TRUE])
-m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_X11_TRUE$])
-m4trace:configure.ac:1140: -1- AC_SUBST([HAVE_X11_FALSE])
-m4trace:configure.ac:1140: -1- AC_SUBST_TRACE([HAVE_X11_FALSE])
-m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_X11_FALSE$])
-m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_X11_TRUE])
-m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_X11_FALSE])
-m4trace:configure.ac:1141: -1- AM_CONDITIONAL([HAVE_ICU], [test "$with_icu" = "yes"])
-m4trace:configure.ac:1141: -1- AC_SUBST([HAVE_ICU_TRUE])
-m4trace:configure.ac:1141: -1- AC_SUBST_TRACE([HAVE_ICU_TRUE])
-m4trace:configure.ac:1141: -1- m4_pattern_allow([^HAVE_ICU_TRUE$])
-m4trace:configure.ac:1141: -1- AC_SUBST([HAVE_ICU_FALSE])
-m4trace:configure.ac:1141: -1- AC_SUBST_TRACE([HAVE_ICU_FALSE])
-m4trace:configure.ac:1141: -1- m4_pattern_allow([^HAVE_ICU_FALSE$])
-m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_TRUE])
-m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_FALSE])
-m4trace:configure.ac:1142: -1- AM_CONDITIONAL([WITH_KERNEL_MODULES], [test "$with_kernel_modules" = "yes"])
-m4trace:configure.ac:1142: -1- AC_SUBST([WITH_KERNEL_MODULES_TRUE])
-m4trace:configure.ac:1142: -1- AC_SUBST_TRACE([WITH_KERNEL_MODULES_TRUE])
-m4trace:configure.ac:1142: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_TRUE$])
-m4trace:configure.ac:1142: -1- AC_SUBST([WITH_KERNEL_MODULES_FALSE])
-m4trace:configure.ac:1142: -1- AC_SUBST_TRACE([WITH_KERNEL_MODULES_FALSE])
-m4trace:configure.ac:1142: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_FALSE$])
-m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_TRUE])
-m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_FALSE])
-m4trace:configure.ac:1143: -1- AM_CONDITIONAL([HAVE_XSM], [test "$have_xsm" = "yes"])
-m4trace:configure.ac:1143: -1- AC_SUBST([HAVE_XSM_TRUE])
-m4trace:configure.ac:1143: -1- AC_SUBST_TRACE([HAVE_XSM_TRUE])
-m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XSM_TRUE$])
-m4trace:configure.ac:1143: -1- AC_SUBST([HAVE_XSM_FALSE])
-m4trace:configure.ac:1143: -1- AC_SUBST_TRACE([HAVE_XSM_FALSE])
-m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XSM_FALSE$])
-m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_TRUE])
-m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_FALSE])
-m4trace:configure.ac:1144: -1- AM_CONDITIONAL([HAVE_XCOMPOSITE], [test "$have_xcomposite" = "yes"])
-m4trace:configure.ac:1144: -1- AC_SUBST([HAVE_XCOMPOSITE_TRUE])
-m4trace:configure.ac:1144: -1- AC_SUBST_TRACE([HAVE_XCOMPOSITE_TRUE])
-m4trace:configure.ac:1144: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_TRUE$])
-m4trace:configure.ac:1144: -1- AC_SUBST([HAVE_XCOMPOSITE_FALSE])
-m4trace:configure.ac:1144: -1- AC_SUBST_TRACE([HAVE_XCOMPOSITE_FALSE])
-m4trace:configure.ac:1144: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_FALSE$])
-m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_TRUE])
-m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_FALSE])
-m4trace:configure.ac:1145: -1- AM_CONDITIONAL([ENABLE_TESTS], [test "$have_cunit" = "yes"])
-m4trace:configure.ac:1145: -1- AC_SUBST([ENABLE_TESTS_TRUE])
-m4trace:configure.ac:1145: -1- AC_SUBST_TRACE([ENABLE_TESTS_TRUE])
-m4trace:configure.ac:1145: -1- m4_pattern_allow([^ENABLE_TESTS_TRUE$])
-m4trace:configure.ac:1145: -1- AC_SUBST([ENABLE_TESTS_FALSE])
-m4trace:configure.ac:1145: -1- AC_SUBST_TRACE([ENABLE_TESTS_FALSE])
-m4trace:configure.ac:1145: -1- m4_pattern_allow([^ENABLE_TESTS_FALSE$])
-m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_TRUE])
-m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_FALSE])
-m4trace:configure.ac:1146: -1- AM_CONDITIONAL([WITH_ROOT_PRIVILEGES], [test "$with_root_privileges" = "yes"])
-m4trace:configure.ac:1146: -1- AC_SUBST([WITH_ROOT_PRIVILEGES_TRUE])
-m4trace:configure.ac:1146: -1- AC_SUBST_TRACE([WITH_ROOT_PRIVILEGES_TRUE])
-m4trace:configure.ac:1146: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_TRUE$])
-m4trace:configure.ac:1146: -1- AC_SUBST([WITH_ROOT_PRIVILEGES_FALSE])
-m4trace:configure.ac:1146: -1- AC_SUBST_TRACE([WITH_ROOT_PRIVILEGES_FALSE])
-m4trace:configure.ac:1146: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_FALSE$])
-m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_TRUE])
-m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_FALSE])
-m4trace:configure.ac:1147: -1- AM_CONDITIONAL([HAVE_DNET], [test "$have_dnet" = "yes"])
-m4trace:configure.ac:1147: -1- AC_SUBST([HAVE_DNET_TRUE])
-m4trace:configure.ac:1147: -1- AC_SUBST_TRACE([HAVE_DNET_TRUE])
-m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DNET_TRUE$])
-m4trace:configure.ac:1147: -1- AC_SUBST([HAVE_DNET_FALSE])
-m4trace:configure.ac:1147: -1- AC_SUBST_TRACE([HAVE_DNET_FALSE])
-m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DNET_FALSE$])
-m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_TRUE])
-m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_FALSE])
-m4trace:configure.ac:1148: -1- AM_CONDITIONAL([HAVE_DOXYGEN], [test "$have_doxygen" = "yes"])
-m4trace:configure.ac:1148: -1- AC_SUBST([HAVE_DOXYGEN_TRUE])
-m4trace:configure.ac:1148: -1- AC_SUBST_TRACE([HAVE_DOXYGEN_TRUE])
-m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_DOXYGEN_TRUE$])
-m4trace:configure.ac:1148: -1- AC_SUBST([HAVE_DOXYGEN_FALSE])
-m4trace:configure.ac:1148: -1- AC_SUBST_TRACE([HAVE_DOXYGEN_FALSE])
-m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_DOXYGEN_FALSE$])
-m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_TRUE])
-m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_FALSE])
-m4trace:configure.ac:1149: -1- AM_CONDITIONAL([HAVE_FUSE], [test "$have_fuse" = "yes"])
-m4trace:configure.ac:1149: -1- AC_SUBST([HAVE_FUSE_TRUE])
-m4trace:configure.ac:1149: -1- AC_SUBST_TRACE([HAVE_FUSE_TRUE])
-m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_FUSE_TRUE$])
-m4trace:configure.ac:1149: -1- AC_SUBST([HAVE_FUSE_FALSE])
-m4trace:configure.ac:1149: -1- AC_SUBST_TRACE([HAVE_FUSE_FALSE])
-m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_FUSE_FALSE$])
-m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_TRUE])
-m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_FALSE])
-m4trace:configure.ac:1150: -1- AM_CONDITIONAL([HAVE_GNU_LD], [test "$with_gnu_ld" = "yes"])
-m4trace:configure.ac:1150: -1- AC_SUBST([HAVE_GNU_LD_TRUE])
-m4trace:configure.ac:1150: -1- AC_SUBST_TRACE([HAVE_GNU_LD_TRUE])
-m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GNU_LD_TRUE$])
-m4trace:configure.ac:1150: -1- AC_SUBST([HAVE_GNU_LD_FALSE])
-m4trace:configure.ac:1150: -1- AC_SUBST_TRACE([HAVE_GNU_LD_FALSE])
-m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GNU_LD_FALSE$])
-m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_TRUE])
-m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_FALSE])
-m4trace:configure.ac:1151: -1- AM_CONDITIONAL([HAVE_GTKMM], [test "$have_x" = "yes" -a "$with_gtkmm" = "yes"])
-m4trace:configure.ac:1151: -1- AC_SUBST([HAVE_GTKMM_TRUE])
-m4trace:configure.ac:1151: -1- AC_SUBST_TRACE([HAVE_GTKMM_TRUE])
-m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_GTKMM_TRUE$])
-m4trace:configure.ac:1151: -1- AC_SUBST([HAVE_GTKMM_FALSE])
-m4trace:configure.ac:1151: -1- AC_SUBST_TRACE([HAVE_GTKMM_FALSE])
-m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_GTKMM_FALSE$])
-m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_TRUE])
-m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_FALSE])
-m4trace:configure.ac:1152: -1- AM_CONDITIONAL([HAVE_PAM], [test "$with_pam" = "yes"])
-m4trace:configure.ac:1152: -1- AC_SUBST([HAVE_PAM_TRUE])
-m4trace:configure.ac:1152: -1- AC_SUBST_TRACE([HAVE_PAM_TRUE])
-m4trace:configure.ac:1152: -1- m4_pattern_allow([^HAVE_PAM_TRUE$])
-m4trace:configure.ac:1152: -1- AC_SUBST([HAVE_PAM_FALSE])
-m4trace:configure.ac:1152: -1- AC_SUBST_TRACE([HAVE_PAM_FALSE])
-m4trace:configure.ac:1152: -1- m4_pattern_allow([^HAVE_PAM_FALSE$])
-m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_TRUE])
-m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_FALSE])
-m4trace:configure.ac:1153: -1- AM_CONDITIONAL([USE_SLASH_PROC], [test "$os" = "linux"])
-m4trace:configure.ac:1153: -1- AC_SUBST([USE_SLASH_PROC_TRUE])
-m4trace:configure.ac:1153: -1- AC_SUBST_TRACE([USE_SLASH_PROC_TRUE])
-m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_SLASH_PROC_TRUE$])
-m4trace:configure.ac:1153: -1- AC_SUBST([USE_SLASH_PROC_FALSE])
-m4trace:configure.ac:1153: -1- AC_SUBST_TRACE([USE_SLASH_PROC_FALSE])
-m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_SLASH_PROC_FALSE$])
-m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_TRUE])
-m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_FALSE])
-m4trace:configure.ac:1154: -1- AM_CONDITIONAL([USE_PRINTF_WRAPPERS], [test "$bsdPrintfWrappers" = "yes"])
-m4trace:configure.ac:1154: -1- AC_SUBST([USE_PRINTF_WRAPPERS_TRUE])
-m4trace:configure.ac:1154: -1- AC_SUBST_TRACE([USE_PRINTF_WRAPPERS_TRUE])
-m4trace:configure.ac:1154: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_TRUE$])
-m4trace:configure.ac:1154: -1- AC_SUBST([USE_PRINTF_WRAPPERS_FALSE])
-m4trace:configure.ac:1154: -1- AC_SUBST_TRACE([USE_PRINTF_WRAPPERS_FALSE])
-m4trace:configure.ac:1154: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_FALSE$])
-m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_TRUE])
-m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_FALSE])
-m4trace:configure.ac:1155: -1- AM_CONDITIONAL([ENABLE_DEPLOYPKG], [test "$enable_deploypkg" = "yes"])
-m4trace:configure.ac:1155: -1- AC_SUBST([ENABLE_DEPLOYPKG_TRUE])
-m4trace:configure.ac:1155: -1- AC_SUBST_TRACE([ENABLE_DEPLOYPKG_TRUE])
-m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_TRUE$])
-m4trace:configure.ac:1155: -1- AC_SUBST([ENABLE_DEPLOYPKG_FALSE])
-m4trace:configure.ac:1155: -1- AC_SUBST_TRACE([ENABLE_DEPLOYPKG_FALSE])
-m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_FALSE$])
-m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_TRUE])
-m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_FALSE])
-m4trace:configure.ac:1156: -1- AM_CONDITIONAL([ENABLE_GRABBITMQPROXY], [test "$enable_grabbitmqproxy" = "yes"])
-m4trace:configure.ac:1156: -1- AC_SUBST([ENABLE_GRABBITMQPROXY_TRUE])
-m4trace:configure.ac:1156: -1- AC_SUBST_TRACE([ENABLE_GRABBITMQPROXY_TRUE])
-m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_TRUE$])
-m4trace:configure.ac:1156: -1- AC_SUBST([ENABLE_GRABBITMQPROXY_FALSE])
-m4trace:configure.ac:1156: -1- AC_SUBST_TRACE([ENABLE_GRABBITMQPROXY_FALSE])
-m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_FALSE$])
-m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_TRUE])
-m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_FALSE])
-m4trace:configure.ac:1157: -1- AM_CONDITIONAL([ENABLE_VGAUTH], [test "$enable_vgauth" = "yes"])
-m4trace:configure.ac:1157: -1- AC_SUBST([ENABLE_VGAUTH_TRUE])
-m4trace:configure.ac:1157: -1- AC_SUBST_TRACE([ENABLE_VGAUTH_TRUE])
-m4trace:configure.ac:1157: -1- m4_pattern_allow([^ENABLE_VGAUTH_TRUE$])
-m4trace:configure.ac:1157: -1- AC_SUBST([ENABLE_VGAUTH_FALSE])
-m4trace:configure.ac:1157: -1- AC_SUBST_TRACE([ENABLE_VGAUTH_FALSE])
-m4trace:configure.ac:1157: -1- m4_pattern_allow([^ENABLE_VGAUTH_FALSE$])
-m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_TRUE])
-m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_FALSE])
-m4trace:configure.ac:1158: -1- AM_CONDITIONAL([HAVE_VSOCK], [test "$os" = "linux"])
-m4trace:configure.ac:1158: -1- AC_SUBST([HAVE_VSOCK_TRUE])
-m4trace:configure.ac:1158: -1- AC_SUBST_TRACE([HAVE_VSOCK_TRUE])
-m4trace:configure.ac:1158: -1- m4_pattern_allow([^HAVE_VSOCK_TRUE$])
-m4trace:configure.ac:1158: -1- AC_SUBST([HAVE_VSOCK_FALSE])
-m4trace:configure.ac:1158: -1- AC_SUBST_TRACE([HAVE_VSOCK_FALSE])
-m4trace:configure.ac:1158: -1- m4_pattern_allow([^HAVE_VSOCK_FALSE$])
-m4trace:configure.ac:1158: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_TRUE])
-m4trace:configure.ac:1158: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_FALSE])
-m4trace:configure.ac:1161: -1- AC_DEFINE_TRACE_LITERAL([NO_XSM])
-m4trace:configure.ac:1161: -1- m4_pattern_allow([^NO_XSM$])
-m4trace:configure.ac:1165: -1- AC_DEFINE_TRACE_LITERAL([NO_XCOMPOSITE])
-m4trace:configure.ac:1165: -1- m4_pattern_allow([^NO_XCOMPOSITE$])
-m4trace:configure.ac:1177: -1- AC_DEFINE_TRACE_LITERAL([NO_MULTIMON])
-m4trace:configure.ac:1177: -1- m4_pattern_allow([^NO_MULTIMON$])
-m4trace:configure.ac:1177: -1- AH_OUTPUT([NO_MULTIMON], [/* Define to 1 if building without multimon support. */
+m4trace:configure.ac:1132: -1- AM_CONDITIONAL([BUILD_HGFSMOUNTER], [test "$buildHgfsmounter" = "yes"])
+m4trace:configure.ac:1132: -1- AC_SUBST([BUILD_HGFSMOUNTER_TRUE])
+m4trace:configure.ac:1132: -1- AC_SUBST_TRACE([BUILD_HGFSMOUNTER_TRUE])
+m4trace:configure.ac:1132: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_TRUE$])
+m4trace:configure.ac:1132: -1- AC_SUBST([BUILD_HGFSMOUNTER_FALSE])
+m4trace:configure.ac:1132: -1- AC_SUBST_TRACE([BUILD_HGFSMOUNTER_FALSE])
+m4trace:configure.ac:1132: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_FALSE$])
+m4trace:configure.ac:1132: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_TRUE])
+m4trace:configure.ac:1132: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_FALSE])
+m4trace:configure.ac:1133: -1- AM_CONDITIONAL([LINUX], [test "$os" = "linux"])
+m4trace:configure.ac:1133: -1- AC_SUBST([LINUX_TRUE])
+m4trace:configure.ac:1133: -1- AC_SUBST_TRACE([LINUX_TRUE])
+m4trace:configure.ac:1133: -1- m4_pattern_allow([^LINUX_TRUE$])
+m4trace:configure.ac:1133: -1- AC_SUBST([LINUX_FALSE])
+m4trace:configure.ac:1133: -1- AC_SUBST_TRACE([LINUX_FALSE])
+m4trace:configure.ac:1133: -1- m4_pattern_allow([^LINUX_FALSE$])
+m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([LINUX_TRUE])
+m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([LINUX_FALSE])
+m4trace:configure.ac:1134: -1- AM_CONDITIONAL([SOLARIS], [test "$os" = "solaris"])
+m4trace:configure.ac:1134: -1- AC_SUBST([SOLARIS_TRUE])
+m4trace:configure.ac:1134: -1- AC_SUBST_TRACE([SOLARIS_TRUE])
+m4trace:configure.ac:1134: -1- m4_pattern_allow([^SOLARIS_TRUE$])
+m4trace:configure.ac:1134: -1- AC_SUBST([SOLARIS_FALSE])
+m4trace:configure.ac:1134: -1- AC_SUBST_TRACE([SOLARIS_FALSE])
+m4trace:configure.ac:1134: -1- m4_pattern_allow([^SOLARIS_FALSE$])
+m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([SOLARIS_TRUE])
+m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([SOLARIS_FALSE])
+m4trace:configure.ac:1135: -1- AM_CONDITIONAL([FREEBSD], [test "$os" = "freebsd" -o "$os" = "kfreebsd-gnu"])
+m4trace:configure.ac:1135: -1- AC_SUBST([FREEBSD_TRUE])
+m4trace:configure.ac:1135: -1- AC_SUBST_TRACE([FREEBSD_TRUE])
+m4trace:configure.ac:1135: -1- m4_pattern_allow([^FREEBSD_TRUE$])
+m4trace:configure.ac:1135: -1- AC_SUBST([FREEBSD_FALSE])
+m4trace:configure.ac:1135: -1- AC_SUBST_TRACE([FREEBSD_FALSE])
+m4trace:configure.ac:1135: -1- m4_pattern_allow([^FREEBSD_FALSE$])
+m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([FREEBSD_TRUE])
+m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([FREEBSD_FALSE])
+m4trace:configure.ac:1136: -1- AM_CONDITIONAL([FREEBSD_CUSTOM_SYSDIR], [test \( "$os" = "freebsd" -o "$os" = "kfreebsd-gnu" \) -a -n "$SYSDIR"])
+m4trace:configure.ac:1136: -1- AC_SUBST([FREEBSD_CUSTOM_SYSDIR_TRUE])
+m4trace:configure.ac:1136: -1- AC_SUBST_TRACE([FREEBSD_CUSTOM_SYSDIR_TRUE])
+m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_TRUE$])
+m4trace:configure.ac:1136: -1- AC_SUBST([FREEBSD_CUSTOM_SYSDIR_FALSE])
+m4trace:configure.ac:1136: -1- AC_SUBST_TRACE([FREEBSD_CUSTOM_SYSDIR_FALSE])
+m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_FALSE$])
+m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_TRUE])
+m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_FALSE])
+m4trace:configure.ac:1138: -1- AM_CONDITIONAL([THIRTY_TWO_BIT_USERSPACE], [test "$userSpaceBitness" = "32"])
+m4trace:configure.ac:1138: -1- AC_SUBST([THIRTY_TWO_BIT_USERSPACE_TRUE])
+m4trace:configure.ac:1138: -1- AC_SUBST_TRACE([THIRTY_TWO_BIT_USERSPACE_TRUE])
+m4trace:configure.ac:1138: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_TRUE$])
+m4trace:configure.ac:1138: -1- AC_SUBST([THIRTY_TWO_BIT_USERSPACE_FALSE])
+m4trace:configure.ac:1138: -1- AC_SUBST_TRACE([THIRTY_TWO_BIT_USERSPACE_FALSE])
+m4trace:configure.ac:1138: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_FALSE$])
+m4trace:configure.ac:1138: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_TRUE])
+m4trace:configure.ac:1138: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_FALSE])
+m4trace:configure.ac:1139: -1- AM_CONDITIONAL([HAVE_X11], [test "$have_x" = "yes"])
+m4trace:configure.ac:1139: -1- AC_SUBST([HAVE_X11_TRUE])
+m4trace:configure.ac:1139: -1- AC_SUBST_TRACE([HAVE_X11_TRUE])
+m4trace:configure.ac:1139: -1- m4_pattern_allow([^HAVE_X11_TRUE$])
+m4trace:configure.ac:1139: -1- AC_SUBST([HAVE_X11_FALSE])
+m4trace:configure.ac:1139: -1- AC_SUBST_TRACE([HAVE_X11_FALSE])
+m4trace:configure.ac:1139: -1- m4_pattern_allow([^HAVE_X11_FALSE$])
+m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([HAVE_X11_TRUE])
+m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([HAVE_X11_FALSE])
+m4trace:configure.ac:1140: -1- AM_CONDITIONAL([HAVE_ICU], [test "$with_icu" = "yes"])
+m4trace:configure.ac:1140: -1- AC_SUBST([HAVE_ICU_TRUE])
+m4trace:configure.ac:1140: -1- AC_SUBST_TRACE([HAVE_ICU_TRUE])
+m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_ICU_TRUE$])
+m4trace:configure.ac:1140: -1- AC_SUBST([HAVE_ICU_FALSE])
+m4trace:configure.ac:1140: -1- AC_SUBST_TRACE([HAVE_ICU_FALSE])
+m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_ICU_FALSE$])
+m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_TRUE])
+m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_FALSE])
+m4trace:configure.ac:1141: -1- AM_CONDITIONAL([WITH_KERNEL_MODULES], [test "$with_kernel_modules" = "yes"])
+m4trace:configure.ac:1141: -1- AC_SUBST([WITH_KERNEL_MODULES_TRUE])
+m4trace:configure.ac:1141: -1- AC_SUBST_TRACE([WITH_KERNEL_MODULES_TRUE])
+m4trace:configure.ac:1141: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_TRUE$])
+m4trace:configure.ac:1141: -1- AC_SUBST([WITH_KERNEL_MODULES_FALSE])
+m4trace:configure.ac:1141: -1- AC_SUBST_TRACE([WITH_KERNEL_MODULES_FALSE])
+m4trace:configure.ac:1141: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_FALSE$])
+m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_TRUE])
+m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_FALSE])
+m4trace:configure.ac:1142: -1- AM_CONDITIONAL([HAVE_XSM], [test "$have_xsm" = "yes"])
+m4trace:configure.ac:1142: -1- AC_SUBST([HAVE_XSM_TRUE])
+m4trace:configure.ac:1142: -1- AC_SUBST_TRACE([HAVE_XSM_TRUE])
+m4trace:configure.ac:1142: -1- m4_pattern_allow([^HAVE_XSM_TRUE$])
+m4trace:configure.ac:1142: -1- AC_SUBST([HAVE_XSM_FALSE])
+m4trace:configure.ac:1142: -1- AC_SUBST_TRACE([HAVE_XSM_FALSE])
+m4trace:configure.ac:1142: -1- m4_pattern_allow([^HAVE_XSM_FALSE$])
+m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_TRUE])
+m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_FALSE])
+m4trace:configure.ac:1143: -1- AM_CONDITIONAL([HAVE_XCOMPOSITE], [test "$have_xcomposite" = "yes"])
+m4trace:configure.ac:1143: -1- AC_SUBST([HAVE_XCOMPOSITE_TRUE])
+m4trace:configure.ac:1143: -1- AC_SUBST_TRACE([HAVE_XCOMPOSITE_TRUE])
+m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_TRUE$])
+m4trace:configure.ac:1143: -1- AC_SUBST([HAVE_XCOMPOSITE_FALSE])
+m4trace:configure.ac:1143: -1- AC_SUBST_TRACE([HAVE_XCOMPOSITE_FALSE])
+m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_FALSE$])
+m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_TRUE])
+m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_FALSE])
+m4trace:configure.ac:1144: -1- AM_CONDITIONAL([ENABLE_TESTS], [test "$have_cunit" = "yes"])
+m4trace:configure.ac:1144: -1- AC_SUBST([ENABLE_TESTS_TRUE])
+m4trace:configure.ac:1144: -1- AC_SUBST_TRACE([ENABLE_TESTS_TRUE])
+m4trace:configure.ac:1144: -1- m4_pattern_allow([^ENABLE_TESTS_TRUE$])
+m4trace:configure.ac:1144: -1- AC_SUBST([ENABLE_TESTS_FALSE])
+m4trace:configure.ac:1144: -1- AC_SUBST_TRACE([ENABLE_TESTS_FALSE])
+m4trace:configure.ac:1144: -1- m4_pattern_allow([^ENABLE_TESTS_FALSE$])
+m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_TRUE])
+m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_FALSE])
+m4trace:configure.ac:1145: -1- AM_CONDITIONAL([WITH_ROOT_PRIVILEGES], [test "$with_root_privileges" = "yes"])
+m4trace:configure.ac:1145: -1- AC_SUBST([WITH_ROOT_PRIVILEGES_TRUE])
+m4trace:configure.ac:1145: -1- AC_SUBST_TRACE([WITH_ROOT_PRIVILEGES_TRUE])
+m4trace:configure.ac:1145: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_TRUE$])
+m4trace:configure.ac:1145: -1- AC_SUBST([WITH_ROOT_PRIVILEGES_FALSE])
+m4trace:configure.ac:1145: -1- AC_SUBST_TRACE([WITH_ROOT_PRIVILEGES_FALSE])
+m4trace:configure.ac:1145: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_FALSE$])
+m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_TRUE])
+m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_FALSE])
+m4trace:configure.ac:1146: -1- AM_CONDITIONAL([HAVE_DNET], [test "$have_dnet" = "yes"])
+m4trace:configure.ac:1146: -1- AC_SUBST([HAVE_DNET_TRUE])
+m4trace:configure.ac:1146: -1- AC_SUBST_TRACE([HAVE_DNET_TRUE])
+m4trace:configure.ac:1146: -1- m4_pattern_allow([^HAVE_DNET_TRUE$])
+m4trace:configure.ac:1146: -1- AC_SUBST([HAVE_DNET_FALSE])
+m4trace:configure.ac:1146: -1- AC_SUBST_TRACE([HAVE_DNET_FALSE])
+m4trace:configure.ac:1146: -1- m4_pattern_allow([^HAVE_DNET_FALSE$])
+m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_TRUE])
+m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_FALSE])
+m4trace:configure.ac:1147: -1- AM_CONDITIONAL([HAVE_DOXYGEN], [test "$have_doxygen" = "yes"])
+m4trace:configure.ac:1147: -1- AC_SUBST([HAVE_DOXYGEN_TRUE])
+m4trace:configure.ac:1147: -1- AC_SUBST_TRACE([HAVE_DOXYGEN_TRUE])
+m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DOXYGEN_TRUE$])
+m4trace:configure.ac:1147: -1- AC_SUBST([HAVE_DOXYGEN_FALSE])
+m4trace:configure.ac:1147: -1- AC_SUBST_TRACE([HAVE_DOXYGEN_FALSE])
+m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DOXYGEN_FALSE$])
+m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_TRUE])
+m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_FALSE])
+m4trace:configure.ac:1148: -1- AM_CONDITIONAL([HAVE_FUSE], [test "$have_fuse" = "yes"])
+m4trace:configure.ac:1148: -1- AC_SUBST([HAVE_FUSE_TRUE])
+m4trace:configure.ac:1148: -1- AC_SUBST_TRACE([HAVE_FUSE_TRUE])
+m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_FUSE_TRUE$])
+m4trace:configure.ac:1148: -1- AC_SUBST([HAVE_FUSE_FALSE])
+m4trace:configure.ac:1148: -1- AC_SUBST_TRACE([HAVE_FUSE_FALSE])
+m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_FUSE_FALSE$])
+m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_TRUE])
+m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_FALSE])
+m4trace:configure.ac:1149: -1- AM_CONDITIONAL([HAVE_GNU_LD], [test "$with_gnu_ld" = "yes"])
+m4trace:configure.ac:1149: -1- AC_SUBST([HAVE_GNU_LD_TRUE])
+m4trace:configure.ac:1149: -1- AC_SUBST_TRACE([HAVE_GNU_LD_TRUE])
+m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_GNU_LD_TRUE$])
+m4trace:configure.ac:1149: -1- AC_SUBST([HAVE_GNU_LD_FALSE])
+m4trace:configure.ac:1149: -1- AC_SUBST_TRACE([HAVE_GNU_LD_FALSE])
+m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_GNU_LD_FALSE$])
+m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_TRUE])
+m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_FALSE])
+m4trace:configure.ac:1150: -1- AM_CONDITIONAL([HAVE_GTKMM], [test "$have_x" = "yes" -a "$with_gtkmm" = "yes"])
+m4trace:configure.ac:1150: -1- AC_SUBST([HAVE_GTKMM_TRUE])
+m4trace:configure.ac:1150: -1- AC_SUBST_TRACE([HAVE_GTKMM_TRUE])
+m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GTKMM_TRUE$])
+m4trace:configure.ac:1150: -1- AC_SUBST([HAVE_GTKMM_FALSE])
+m4trace:configure.ac:1150: -1- AC_SUBST_TRACE([HAVE_GTKMM_FALSE])
+m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GTKMM_FALSE$])
+m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_TRUE])
+m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_FALSE])
+m4trace:configure.ac:1151: -1- AM_CONDITIONAL([HAVE_PAM], [test "$with_pam" = "yes"])
+m4trace:configure.ac:1151: -1- AC_SUBST([HAVE_PAM_TRUE])
+m4trace:configure.ac:1151: -1- AC_SUBST_TRACE([HAVE_PAM_TRUE])
+m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_PAM_TRUE$])
+m4trace:configure.ac:1151: -1- AC_SUBST([HAVE_PAM_FALSE])
+m4trace:configure.ac:1151: -1- AC_SUBST_TRACE([HAVE_PAM_FALSE])
+m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_PAM_FALSE$])
+m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_TRUE])
+m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_FALSE])
+m4trace:configure.ac:1152: -1- AM_CONDITIONAL([USE_SLASH_PROC], [test "$os" = "linux"])
+m4trace:configure.ac:1152: -1- AC_SUBST([USE_SLASH_PROC_TRUE])
+m4trace:configure.ac:1152: -1- AC_SUBST_TRACE([USE_SLASH_PROC_TRUE])
+m4trace:configure.ac:1152: -1- m4_pattern_allow([^USE_SLASH_PROC_TRUE$])
+m4trace:configure.ac:1152: -1- AC_SUBST([USE_SLASH_PROC_FALSE])
+m4trace:configure.ac:1152: -1- AC_SUBST_TRACE([USE_SLASH_PROC_FALSE])
+m4trace:configure.ac:1152: -1- m4_pattern_allow([^USE_SLASH_PROC_FALSE$])
+m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_TRUE])
+m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_FALSE])
+m4trace:configure.ac:1153: -1- AM_CONDITIONAL([USE_PRINTF_WRAPPERS], [test "$bsdPrintfWrappers" = "yes"])
+m4trace:configure.ac:1153: -1- AC_SUBST([USE_PRINTF_WRAPPERS_TRUE])
+m4trace:configure.ac:1153: -1- AC_SUBST_TRACE([USE_PRINTF_WRAPPERS_TRUE])
+m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_TRUE$])
+m4trace:configure.ac:1153: -1- AC_SUBST([USE_PRINTF_WRAPPERS_FALSE])
+m4trace:configure.ac:1153: -1- AC_SUBST_TRACE([USE_PRINTF_WRAPPERS_FALSE])
+m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_FALSE$])
+m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_TRUE])
+m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_FALSE])
+m4trace:configure.ac:1154: -1- AM_CONDITIONAL([ENABLE_DEPLOYPKG], [test "$enable_deploypkg" = "yes"])
+m4trace:configure.ac:1154: -1- AC_SUBST([ENABLE_DEPLOYPKG_TRUE])
+m4trace:configure.ac:1154: -1- AC_SUBST_TRACE([ENABLE_DEPLOYPKG_TRUE])
+m4trace:configure.ac:1154: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_TRUE$])
+m4trace:configure.ac:1154: -1- AC_SUBST([ENABLE_DEPLOYPKG_FALSE])
+m4trace:configure.ac:1154: -1- AC_SUBST_TRACE([ENABLE_DEPLOYPKG_FALSE])
+m4trace:configure.ac:1154: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_FALSE$])
+m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_TRUE])
+m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_FALSE])
+m4trace:configure.ac:1155: -1- AM_CONDITIONAL([ENABLE_GRABBITMQPROXY], [test "$enable_grabbitmqproxy" = "yes"])
+m4trace:configure.ac:1155: -1- AC_SUBST([ENABLE_GRABBITMQPROXY_TRUE])
+m4trace:configure.ac:1155: -1- AC_SUBST_TRACE([ENABLE_GRABBITMQPROXY_TRUE])
+m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_TRUE$])
+m4trace:configure.ac:1155: -1- AC_SUBST([ENABLE_GRABBITMQPROXY_FALSE])
+m4trace:configure.ac:1155: -1- AC_SUBST_TRACE([ENABLE_GRABBITMQPROXY_FALSE])
+m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_FALSE$])
+m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_TRUE])
+m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_FALSE])
+m4trace:configure.ac:1156: -1- AM_CONDITIONAL([ENABLE_VGAUTH], [test "$enable_vgauth" = "yes"])
+m4trace:configure.ac:1156: -1- AC_SUBST([ENABLE_VGAUTH_TRUE])
+m4trace:configure.ac:1156: -1- AC_SUBST_TRACE([ENABLE_VGAUTH_TRUE])
+m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_VGAUTH_TRUE$])
+m4trace:configure.ac:1156: -1- AC_SUBST([ENABLE_VGAUTH_FALSE])
+m4trace:configure.ac:1156: -1- AC_SUBST_TRACE([ENABLE_VGAUTH_FALSE])
+m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_VGAUTH_FALSE$])
+m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_TRUE])
+m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_FALSE])
+m4trace:configure.ac:1157: -1- AM_CONDITIONAL([HAVE_VSOCK], [test "$os" = "linux"])
+m4trace:configure.ac:1157: -1- AC_SUBST([HAVE_VSOCK_TRUE])
+m4trace:configure.ac:1157: -1- AC_SUBST_TRACE([HAVE_VSOCK_TRUE])
+m4trace:configure.ac:1157: -1- m4_pattern_allow([^HAVE_VSOCK_TRUE$])
+m4trace:configure.ac:1157: -1- AC_SUBST([HAVE_VSOCK_FALSE])
+m4trace:configure.ac:1157: -1- AC_SUBST_TRACE([HAVE_VSOCK_FALSE])
+m4trace:configure.ac:1157: -1- m4_pattern_allow([^HAVE_VSOCK_FALSE$])
+m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_TRUE])
+m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_FALSE])
+m4trace:configure.ac:1160: -1- AC_DEFINE_TRACE_LITERAL([NO_XSM])
+m4trace:configure.ac:1160: -1- m4_pattern_allow([^NO_XSM$])
+m4trace:configure.ac:1164: -1- AC_DEFINE_TRACE_LITERAL([NO_XCOMPOSITE])
+m4trace:configure.ac:1164: -1- m4_pattern_allow([^NO_XCOMPOSITE$])
+m4trace:configure.ac:1176: -1- AC_DEFINE_TRACE_LITERAL([NO_MULTIMON])
+m4trace:configure.ac:1176: -1- m4_pattern_allow([^NO_MULTIMON$])
+m4trace:configure.ac:1176: -1- AH_OUTPUT([NO_MULTIMON], [/* Define to 1 if building without multimon support. */
#undef NO_MULTIMON])
-m4trace:configure.ac:1219: -1- AC_SUBST([HGFS_LIBS])
-m4trace:configure.ac:1219: -1- AC_SUBST_TRACE([HGFS_LIBS])
-m4trace:configure.ac:1219: -1- m4_pattern_allow([^HGFS_LIBS$])
-m4trace:configure.ac:1220: -1- AC_SUBST([TOOLS_VERSION])
-m4trace:configure.ac:1220: -1- AC_SUBST_TRACE([TOOLS_VERSION])
-m4trace:configure.ac:1220: -1- m4_pattern_allow([^TOOLS_VERSION$])
-m4trace:configure.ac:1221: -1- AC_SUBST([TARGET_OS])
-m4trace:configure.ac:1221: -1- AC_SUBST_TRACE([TARGET_OS])
-m4trace:configure.ac:1221: -1- m4_pattern_allow([^TARGET_OS$])
-m4trace:configure.ac:1222: -1- AC_SUBST([KERNEL_RELEASE])
-m4trace:configure.ac:1222: -1- AC_SUBST_TRACE([KERNEL_RELEASE])
-m4trace:configure.ac:1222: -1- m4_pattern_allow([^KERNEL_RELEASE$])
-m4trace:configure.ac:1223: -1- AC_SUBST([LINUXINCLUDE])
-m4trace:configure.ac:1223: -1- AC_SUBST_TRACE([LINUXINCLUDE])
-m4trace:configure.ac:1223: -1- m4_pattern_allow([^LINUXINCLUDE$])
-m4trace:configure.ac:1224: -1- AC_SUBST([MODULES_OS])
-m4trace:configure.ac:1224: -1- AC_SUBST_TRACE([MODULES_OS])
-m4trace:configure.ac:1224: -1- m4_pattern_allow([^MODULES_OS$])
-m4trace:configure.ac:1225: -1- AC_SUBST([MODULES_DIR])
-m4trace:configure.ac:1225: -1- AC_SUBST_TRACE([MODULES_DIR])
-m4trace:configure.ac:1225: -1- m4_pattern_allow([^MODULES_DIR$])
-m4trace:configure.ac:1226: -1- AC_SUBST([MODULES])
-m4trace:configure.ac:1226: -1- AC_SUBST_TRACE([MODULES])
-m4trace:configure.ac:1226: -1- m4_pattern_allow([^MODULES$])
-m4trace:configure.ac:1227: -1- AC_SUBST([COMMON_XLIBS])
-m4trace:configure.ac:1227: -1- AC_SUBST_TRACE([COMMON_XLIBS])
-m4trace:configure.ac:1227: -1- m4_pattern_allow([^COMMON_XLIBS$])
-m4trace:configure.ac:1228: -1- AC_SUBST([XSM_LIBS])
-m4trace:configure.ac:1228: -1- AC_SUBST_TRACE([XSM_LIBS])
-m4trace:configure.ac:1228: -1- m4_pattern_allow([^XSM_LIBS$])
-m4trace:configure.ac:1229: -1- AC_SUBST([XCOMPOSITE_LIBS])
-m4trace:configure.ac:1229: -1- AC_SUBST_TRACE([XCOMPOSITE_LIBS])
-m4trace:configure.ac:1229: -1- m4_pattern_allow([^XCOMPOSITE_LIBS$])
-m4trace:configure.ac:1230: -1- AC_SUBST([PAM_PREFIX])
-m4trace:configure.ac:1230: -1- AC_SUBST_TRACE([PAM_PREFIX])
-m4trace:configure.ac:1230: -1- m4_pattern_allow([^PAM_PREFIX$])
-m4trace:configure.ac:1231: -1- AC_SUBST([PLUGIN_CPPFLAGS])
-m4trace:configure.ac:1231: -1- AC_SUBST_TRACE([PLUGIN_CPPFLAGS])
-m4trace:configure.ac:1231: -1- m4_pattern_allow([^PLUGIN_CPPFLAGS$])
-m4trace:configure.ac:1232: -1- AC_SUBST([PLUGIN_LDFLAGS])
-m4trace:configure.ac:1232: -1- AC_SUBST_TRACE([PLUGIN_LDFLAGS])
-m4trace:configure.ac:1232: -1- m4_pattern_allow([^PLUGIN_LDFLAGS$])
-m4trace:configure.ac:1233: -1- AC_SUBST([VMTOOLS_CPPFLAGS])
-m4trace:configure.ac:1233: -1- AC_SUBST_TRACE([VMTOOLS_CPPFLAGS])
-m4trace:configure.ac:1233: -1- m4_pattern_allow([^VMTOOLS_CPPFLAGS$])
-m4trace:configure.ac:1234: -1- AC_SUBST([VMTOOLS_LIBS])
-m4trace:configure.ac:1234: -1- AC_SUBST_TRACE([VMTOOLS_LIBS])
-m4trace:configure.ac:1234: -1- m4_pattern_allow([^VMTOOLS_LIBS$])
-m4trace:configure.ac:1235: -1- AC_SUBST([RPCGENFLAGS])
-m4trace:configure.ac:1235: -1- AC_SUBST_TRACE([RPCGENFLAGS])
-m4trace:configure.ac:1235: -1- m4_pattern_allow([^RPCGENFLAGS$])
-m4trace:configure.ac:1236: -1- AC_SUBST([XDR_LIBS])
-m4trace:configure.ac:1236: -1- AC_SUBST_TRACE([XDR_LIBS])
-m4trace:configure.ac:1236: -1- m4_pattern_allow([^XDR_LIBS$])
-m4trace:configure.ac:1237: -1- AC_SUBST([TEST_PLUGIN_INSTALLDIR])
-m4trace:configure.ac:1237: -1- AC_SUBST_TRACE([TEST_PLUGIN_INSTALLDIR])
-m4trace:configure.ac:1237: -1- m4_pattern_allow([^TEST_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1238: -1- AC_SUBST([COMMON_PLUGIN_INSTALLDIR])
-m4trace:configure.ac:1238: -1- AC_SUBST_TRACE([COMMON_PLUGIN_INSTALLDIR])
-m4trace:configure.ac:1238: -1- m4_pattern_allow([^COMMON_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1239: -1- AC_SUBST([VMSVC_PLUGIN_INSTALLDIR])
-m4trace:configure.ac:1239: -1- AC_SUBST_TRACE([VMSVC_PLUGIN_INSTALLDIR])
-m4trace:configure.ac:1239: -1- m4_pattern_allow([^VMSVC_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1240: -1- AC_SUBST([VMUSR_PLUGIN_INSTALLDIR])
-m4trace:configure.ac:1240: -1- AC_SUBST_TRACE([VMUSR_PLUGIN_INSTALLDIR])
-m4trace:configure.ac:1240: -1- m4_pattern_allow([^VMUSR_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1245: -1- AC_SUBST([SYSDIR])
-m4trace:configure.ac:1245: -1- AC_SUBST_TRACE([SYSDIR])
-m4trace:configure.ac:1245: -1- m4_pattern_allow([^SYSDIR$])
-m4trace:configure.ac:1247: -1- AC_SUBST([INSTVMSG])
-m4trace:configure.ac:1247: -1- AC_SUBST_TRACE([INSTVMSG])
-m4trace:configure.ac:1247: -1- m4_pattern_allow([^INSTVMSG$])
-m4trace:configure.ac:1248: -1- AC_SUBST([RPCGEN_WRAPPER])
-m4trace:configure.ac:1248: -1- AC_SUBST_TRACE([RPCGEN_WRAPPER])
-m4trace:configure.ac:1248: -1- m4_pattern_allow([^RPCGEN_WRAPPER$])
-m4trace:configure.ac:1252: -1- AC_SUBST([LIB_AUTH_CPPFLAGS])
-m4trace:configure.ac:1252: -1- AC_SUBST_TRACE([LIB_AUTH_CPPFLAGS])
-m4trace:configure.ac:1252: -1- m4_pattern_allow([^LIB_AUTH_CPPFLAGS$])
-m4trace:configure.ac:1253: -1- AC_SUBST([LIB_IMPERSONATE_CPPFLAGS])
-m4trace:configure.ac:1253: -1- AC_SUBST_TRACE([LIB_IMPERSONATE_CPPFLAGS])
-m4trace:configure.ac:1253: -1- m4_pattern_allow([^LIB_IMPERSONATE_CPPFLAGS$])
-m4trace:configure.ac:1254: -1- AC_SUBST([LIB_USER_CPPFLAGS])
-m4trace:configure.ac:1254: -1- AC_SUBST_TRACE([LIB_USER_CPPFLAGS])
-m4trace:configure.ac:1254: -1- m4_pattern_allow([^LIB_USER_CPPFLAGS$])
-m4trace:configure.ac:1255: -1- AC_SUBST([LIBVMTOOLS_LIBADD])
-m4trace:configure.ac:1255: -1- AC_SUBST_TRACE([LIBVMTOOLS_LIBADD])
-m4trace:configure.ac:1255: -1- m4_pattern_allow([^LIBVMTOOLS_LIBADD$])
-m4trace:configure.ac:1259: -1- AC_SUBST([VIX_LIBADD])
-m4trace:configure.ac:1259: -1- AC_SUBST_TRACE([VIX_LIBADD])
-m4trace:configure.ac:1259: -1- m4_pattern_allow([^VIX_LIBADD$])
-m4trace:configure.ac:1260: -1- AC_SUBST([VGAUTH_LIBADD])
-m4trace:configure.ac:1260: -1- AC_SUBST_TRACE([VGAUTH_LIBADD])
-m4trace:configure.ac:1260: -1- m4_pattern_allow([^VGAUTH_LIBADD$])
-m4trace:configure.ac:1265: -1- AC_CONFIG_FILES([ \
+m4trace:configure.ac:1218: -1- AC_SUBST([HGFS_LIBS])
+m4trace:configure.ac:1218: -1- AC_SUBST_TRACE([HGFS_LIBS])
+m4trace:configure.ac:1218: -1- m4_pattern_allow([^HGFS_LIBS$])
+m4trace:configure.ac:1219: -1- AC_SUBST([TOOLS_VERSION])
+m4trace:configure.ac:1219: -1- AC_SUBST_TRACE([TOOLS_VERSION])
+m4trace:configure.ac:1219: -1- m4_pattern_allow([^TOOLS_VERSION$])
+m4trace:configure.ac:1220: -1- AC_SUBST([TARGET_OS])
+m4trace:configure.ac:1220: -1- AC_SUBST_TRACE([TARGET_OS])
+m4trace:configure.ac:1220: -1- m4_pattern_allow([^TARGET_OS$])
+m4trace:configure.ac:1221: -1- AC_SUBST([KERNEL_RELEASE])
+m4trace:configure.ac:1221: -1- AC_SUBST_TRACE([KERNEL_RELEASE])
+m4trace:configure.ac:1221: -1- m4_pattern_allow([^KERNEL_RELEASE$])
+m4trace:configure.ac:1222: -1- AC_SUBST([LINUXINCLUDE])
+m4trace:configure.ac:1222: -1- AC_SUBST_TRACE([LINUXINCLUDE])
+m4trace:configure.ac:1222: -1- m4_pattern_allow([^LINUXINCLUDE$])
+m4trace:configure.ac:1223: -1- AC_SUBST([MODULES_OS])
+m4trace:configure.ac:1223: -1- AC_SUBST_TRACE([MODULES_OS])
+m4trace:configure.ac:1223: -1- m4_pattern_allow([^MODULES_OS$])
+m4trace:configure.ac:1224: -1- AC_SUBST([MODULES_DIR])
+m4trace:configure.ac:1224: -1- AC_SUBST_TRACE([MODULES_DIR])
+m4trace:configure.ac:1224: -1- m4_pattern_allow([^MODULES_DIR$])
+m4trace:configure.ac:1225: -1- AC_SUBST([MODULES])
+m4trace:configure.ac:1225: -1- AC_SUBST_TRACE([MODULES])
+m4trace:configure.ac:1225: -1- m4_pattern_allow([^MODULES$])
+m4trace:configure.ac:1226: -1- AC_SUBST([COMMON_XLIBS])
+m4trace:configure.ac:1226: -1- AC_SUBST_TRACE([COMMON_XLIBS])
+m4trace:configure.ac:1226: -1- m4_pattern_allow([^COMMON_XLIBS$])
+m4trace:configure.ac:1227: -1- AC_SUBST([XSM_LIBS])
+m4trace:configure.ac:1227: -1- AC_SUBST_TRACE([XSM_LIBS])
+m4trace:configure.ac:1227: -1- m4_pattern_allow([^XSM_LIBS$])
+m4trace:configure.ac:1228: -1- AC_SUBST([XCOMPOSITE_LIBS])
+m4trace:configure.ac:1228: -1- AC_SUBST_TRACE([XCOMPOSITE_LIBS])
+m4trace:configure.ac:1228: -1- m4_pattern_allow([^XCOMPOSITE_LIBS$])
+m4trace:configure.ac:1229: -1- AC_SUBST([PAM_PREFIX])
+m4trace:configure.ac:1229: -1- AC_SUBST_TRACE([PAM_PREFIX])
+m4trace:configure.ac:1229: -1- m4_pattern_allow([^PAM_PREFIX$])
+m4trace:configure.ac:1230: -1- AC_SUBST([PLUGIN_CPPFLAGS])
+m4trace:configure.ac:1230: -1- AC_SUBST_TRACE([PLUGIN_CPPFLAGS])
+m4trace:configure.ac:1230: -1- m4_pattern_allow([^PLUGIN_CPPFLAGS$])
+m4trace:configure.ac:1231: -1- AC_SUBST([PLUGIN_LDFLAGS])
+m4trace:configure.ac:1231: -1- AC_SUBST_TRACE([PLUGIN_LDFLAGS])
+m4trace:configure.ac:1231: -1- m4_pattern_allow([^PLUGIN_LDFLAGS$])
+m4trace:configure.ac:1232: -1- AC_SUBST([VMTOOLS_CPPFLAGS])
+m4trace:configure.ac:1232: -1- AC_SUBST_TRACE([VMTOOLS_CPPFLAGS])
+m4trace:configure.ac:1232: -1- m4_pattern_allow([^VMTOOLS_CPPFLAGS$])
+m4trace:configure.ac:1233: -1- AC_SUBST([VMTOOLS_LIBS])
+m4trace:configure.ac:1233: -1- AC_SUBST_TRACE([VMTOOLS_LIBS])
+m4trace:configure.ac:1233: -1- m4_pattern_allow([^VMTOOLS_LIBS$])
+m4trace:configure.ac:1234: -1- AC_SUBST([RPCGENFLAGS])
+m4trace:configure.ac:1234: -1- AC_SUBST_TRACE([RPCGENFLAGS])
+m4trace:configure.ac:1234: -1- m4_pattern_allow([^RPCGENFLAGS$])
+m4trace:configure.ac:1235: -1- AC_SUBST([XDR_LIBS])
+m4trace:configure.ac:1235: -1- AC_SUBST_TRACE([XDR_LIBS])
+m4trace:configure.ac:1235: -1- m4_pattern_allow([^XDR_LIBS$])
+m4trace:configure.ac:1236: -1- AC_SUBST([TEST_PLUGIN_INSTALLDIR])
+m4trace:configure.ac:1236: -1- AC_SUBST_TRACE([TEST_PLUGIN_INSTALLDIR])
+m4trace:configure.ac:1236: -1- m4_pattern_allow([^TEST_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1237: -1- AC_SUBST([COMMON_PLUGIN_INSTALLDIR])
+m4trace:configure.ac:1237: -1- AC_SUBST_TRACE([COMMON_PLUGIN_INSTALLDIR])
+m4trace:configure.ac:1237: -1- m4_pattern_allow([^COMMON_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1238: -1- AC_SUBST([VMSVC_PLUGIN_INSTALLDIR])
+m4trace:configure.ac:1238: -1- AC_SUBST_TRACE([VMSVC_PLUGIN_INSTALLDIR])
+m4trace:configure.ac:1238: -1- m4_pattern_allow([^VMSVC_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1239: -1- AC_SUBST([VMUSR_PLUGIN_INSTALLDIR])
+m4trace:configure.ac:1239: -1- AC_SUBST_TRACE([VMUSR_PLUGIN_INSTALLDIR])
+m4trace:configure.ac:1239: -1- m4_pattern_allow([^VMUSR_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1244: -1- AC_SUBST([SYSDIR])
+m4trace:configure.ac:1244: -1- AC_SUBST_TRACE([SYSDIR])
+m4trace:configure.ac:1244: -1- m4_pattern_allow([^SYSDIR$])
+m4trace:configure.ac:1246: -1- AC_SUBST([INSTVMSG])
+m4trace:configure.ac:1246: -1- AC_SUBST_TRACE([INSTVMSG])
+m4trace:configure.ac:1246: -1- m4_pattern_allow([^INSTVMSG$])
+m4trace:configure.ac:1247: -1- AC_SUBST([RPCGEN_WRAPPER])
+m4trace:configure.ac:1247: -1- AC_SUBST_TRACE([RPCGEN_WRAPPER])
+m4trace:configure.ac:1247: -1- m4_pattern_allow([^RPCGEN_WRAPPER$])
+m4trace:configure.ac:1251: -1- AC_SUBST([LIB_AUTH_CPPFLAGS])
+m4trace:configure.ac:1251: -1- AC_SUBST_TRACE([LIB_AUTH_CPPFLAGS])
+m4trace:configure.ac:1251: -1- m4_pattern_allow([^LIB_AUTH_CPPFLAGS$])
+m4trace:configure.ac:1252: -1- AC_SUBST([LIB_IMPERSONATE_CPPFLAGS])
+m4trace:configure.ac:1252: -1- AC_SUBST_TRACE([LIB_IMPERSONATE_CPPFLAGS])
+m4trace:configure.ac:1252: -1- m4_pattern_allow([^LIB_IMPERSONATE_CPPFLAGS$])
+m4trace:configure.ac:1253: -1- AC_SUBST([LIB_USER_CPPFLAGS])
+m4trace:configure.ac:1253: -1- AC_SUBST_TRACE([LIB_USER_CPPFLAGS])
+m4trace:configure.ac:1253: -1- m4_pattern_allow([^LIB_USER_CPPFLAGS$])
+m4trace:configure.ac:1254: -1- AC_SUBST([LIBVMTOOLS_LIBADD])
+m4trace:configure.ac:1254: -1- AC_SUBST_TRACE([LIBVMTOOLS_LIBADD])
+m4trace:configure.ac:1254: -1- m4_pattern_allow([^LIBVMTOOLS_LIBADD$])
+m4trace:configure.ac:1258: -1- AC_SUBST([VIX_LIBADD])
+m4trace:configure.ac:1258: -1- AC_SUBST_TRACE([VIX_LIBADD])
+m4trace:configure.ac:1258: -1- m4_pattern_allow([^VIX_LIBADD$])
+m4trace:configure.ac:1259: -1- AC_SUBST([VGAUTH_LIBADD])
+m4trace:configure.ac:1259: -1- AC_SUBST_TRACE([VGAUTH_LIBADD])
+m4trace:configure.ac:1259: -1- m4_pattern_allow([^VGAUTH_LIBADD$])
+m4trace:configure.ac:1264: -1- AC_CONFIG_FILES([ \
Makefile \
lib/Makefile \
lib/appUtil/Makefile \
@@ -1322,6 +1322,7 @@ m4trace:configure.ac:1265: -1- AC_CONFIG_FILES([ \
lib/hgfsServer/Makefile \
lib/hgfsServerManagerGuest/Makefile \
lib/hgfsServerPolicyGuest/Makefile \
+ lib/hgfsUri/Makefile \
lib/impersonate/Makefile \
lib/lock/Makefile \
lib/message/Makefile \
@@ -1330,7 +1331,6 @@ m4trace:configure.ac:1265: -1- AC_CONFIG_FILES([ \
lib/nicInfo/Makefile \
lib/panic/Makefile \
lib/panicDefault/Makefile \
- lib/printer/Makefile \
lib/procMgr/Makefile \
lib/rpcChannel/Makefile \
lib/rpcIn/Makefile \
@@ -1381,6 +1381,7 @@ m4trace:configure.ac:1265: -1- AC_CONFIG_FILES([ \
xferlogs/Makefile \
modules/Makefile \
vmblock-fuse/Makefile \
+ vmhgfs-fuse/Makefile \
vmblockmounter/Makefile \
tests/Makefile \
tests/vmrpcdbg/Makefile \
diff --git a/open-vm-tools/autom4te.cache/traces.2 b/open-vm-tools/autom4te.cache/traces.2
index cfc6fc70..f92eb01a 100644
--- a/open-vm-tools/autom4te.cache/traces.2
+++ b/open-vm-tools/autom4te.cache/traces.2
@@ -1925,7 +1925,7 @@ m4trace:configure.ac:350: -1- m4_pattern_allow([^GTHREAD_CPPFLAGS$])
m4trace:configure.ac:350: -1- m4_pattern_allow([^GTHREAD_LIBS$])
m4trace:configure.ac:359: -1- m4_pattern_allow([^have_genmarshal$])
m4trace:configure.ac:371: -1- AC_VMW_CHECK_LIB([fuse], [FUSE], [fuse], [], [], [fuse.h], [fuse_main], [have_fuse=yes], [have_fuse=no;
- AC_MSG_WARN([Fuse is missing, vmblock-fuse will be disabled.])])
+ AC_MSG_WARN([Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled.])])
m4trace:configure.ac:371: -1- m4_pattern_allow([^ac_vmw_lib_cfg$])
m4trace:configure.ac:371: -1- m4_pattern_allow([^FUSE_CPPFLAGS$])
m4trace:configure.ac:371: -1- m4_pattern_allow([^FUSE_LIBS$])
@@ -2040,165 +2040,165 @@ m4trace:configure.ac:1011: -1- m4_pattern_allow([^DOT$])
m4trace:configure.ac:1012: -1- m4_pattern_allow([^HAVE_DOT$])
m4trace:configure.ac:1014: -1- m4_pattern_allow([^MSCGEN$])
m4trace:configure.ac:1022: -1- m4_pattern_allow([^MSCGEN_DIR$])
-m4trace:configure.ac:1133: -1- AM_CONDITIONAL([BUILD_HGFSMOUNTER], [test "$buildHgfsmounter" = "yes"])
-m4trace:configure.ac:1133: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_TRUE$])
-m4trace:configure.ac:1133: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_FALSE$])
-m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_TRUE])
-m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_FALSE])
-m4trace:configure.ac:1134: -1- AM_CONDITIONAL([LINUX], [test "$os" = "linux"])
-m4trace:configure.ac:1134: -1- m4_pattern_allow([^LINUX_TRUE$])
-m4trace:configure.ac:1134: -1- m4_pattern_allow([^LINUX_FALSE$])
-m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([LINUX_TRUE])
-m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([LINUX_FALSE])
-m4trace:configure.ac:1135: -1- AM_CONDITIONAL([SOLARIS], [test "$os" = "solaris"])
-m4trace:configure.ac:1135: -1- m4_pattern_allow([^SOLARIS_TRUE$])
-m4trace:configure.ac:1135: -1- m4_pattern_allow([^SOLARIS_FALSE$])
-m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([SOLARIS_TRUE])
-m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([SOLARIS_FALSE])
-m4trace:configure.ac:1136: -1- AM_CONDITIONAL([FREEBSD], [test "$os" = "freebsd" -o "$os" = "kfreebsd-gnu"])
-m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_TRUE$])
-m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_FALSE$])
-m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_TRUE])
-m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_FALSE])
-m4trace:configure.ac:1137: -1- AM_CONDITIONAL([FREEBSD_CUSTOM_SYSDIR], [test \( "$os" = "freebsd" -o "$os" = "kfreebsd-gnu" \) -a -n "$SYSDIR"])
-m4trace:configure.ac:1137: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_TRUE$])
-m4trace:configure.ac:1137: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_FALSE$])
-m4trace:configure.ac:1137: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_TRUE])
-m4trace:configure.ac:1137: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_FALSE])
-m4trace:configure.ac:1139: -1- AM_CONDITIONAL([THIRTY_TWO_BIT_USERSPACE], [test "$userSpaceBitness" = "32"])
-m4trace:configure.ac:1139: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_TRUE$])
-m4trace:configure.ac:1139: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_FALSE$])
-m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_TRUE])
-m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_FALSE])
-m4trace:configure.ac:1140: -1- AM_CONDITIONAL([HAVE_X11], [test "$have_x" = "yes"])
-m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_X11_TRUE$])
-m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_X11_FALSE$])
-m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_X11_TRUE])
-m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_X11_FALSE])
-m4trace:configure.ac:1141: -1- AM_CONDITIONAL([HAVE_ICU], [test "$with_icu" = "yes"])
-m4trace:configure.ac:1141: -1- m4_pattern_allow([^HAVE_ICU_TRUE$])
-m4trace:configure.ac:1141: -1- m4_pattern_allow([^HAVE_ICU_FALSE$])
-m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_TRUE])
-m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_FALSE])
-m4trace:configure.ac:1142: -1- AM_CONDITIONAL([WITH_KERNEL_MODULES], [test "$with_kernel_modules" = "yes"])
-m4trace:configure.ac:1142: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_TRUE$])
-m4trace:configure.ac:1142: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_FALSE$])
-m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_TRUE])
-m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_FALSE])
-m4trace:configure.ac:1143: -1- AM_CONDITIONAL([HAVE_XSM], [test "$have_xsm" = "yes"])
-m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XSM_TRUE$])
-m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XSM_FALSE$])
-m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_TRUE])
-m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_FALSE])
-m4trace:configure.ac:1144: -1- AM_CONDITIONAL([HAVE_XCOMPOSITE], [test "$have_xcomposite" = "yes"])
-m4trace:configure.ac:1144: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_TRUE$])
-m4trace:configure.ac:1144: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_FALSE$])
-m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_TRUE])
-m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_FALSE])
-m4trace:configure.ac:1145: -1- AM_CONDITIONAL([ENABLE_TESTS], [test "$have_cunit" = "yes"])
-m4trace:configure.ac:1145: -1- m4_pattern_allow([^ENABLE_TESTS_TRUE$])
-m4trace:configure.ac:1145: -1- m4_pattern_allow([^ENABLE_TESTS_FALSE$])
-m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_TRUE])
-m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_FALSE])
-m4trace:configure.ac:1146: -1- AM_CONDITIONAL([WITH_ROOT_PRIVILEGES], [test "$with_root_privileges" = "yes"])
-m4trace:configure.ac:1146: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_TRUE$])
-m4trace:configure.ac:1146: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_FALSE$])
-m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_TRUE])
-m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_FALSE])
-m4trace:configure.ac:1147: -1- AM_CONDITIONAL([HAVE_DNET], [test "$have_dnet" = "yes"])
-m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DNET_TRUE$])
-m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DNET_FALSE$])
-m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_TRUE])
-m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_FALSE])
-m4trace:configure.ac:1148: -1- AM_CONDITIONAL([HAVE_DOXYGEN], [test "$have_doxygen" = "yes"])
-m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_DOXYGEN_TRUE$])
-m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_DOXYGEN_FALSE$])
-m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_TRUE])
-m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_FALSE])
-m4trace:configure.ac:1149: -1- AM_CONDITIONAL([HAVE_FUSE], [test "$have_fuse" = "yes"])
-m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_FUSE_TRUE$])
-m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_FUSE_FALSE$])
-m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_TRUE])
-m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_FALSE])
-m4trace:configure.ac:1150: -1- AM_CONDITIONAL([HAVE_GNU_LD], [test "$with_gnu_ld" = "yes"])
-m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GNU_LD_TRUE$])
-m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GNU_LD_FALSE$])
-m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_TRUE])
-m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_FALSE])
-m4trace:configure.ac:1151: -1- AM_CONDITIONAL([HAVE_GTKMM], [test "$have_x" = "yes" -a "$with_gtkmm" = "yes"])
-m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_GTKMM_TRUE$])
-m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_GTKMM_FALSE$])
-m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_TRUE])
-m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_FALSE])
-m4trace:configure.ac:1152: -1- AM_CONDITIONAL([HAVE_PAM], [test "$with_pam" = "yes"])
-m4trace:configure.ac:1152: -1- m4_pattern_allow([^HAVE_PAM_TRUE$])
-m4trace:configure.ac:1152: -1- m4_pattern_allow([^HAVE_PAM_FALSE$])
-m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_TRUE])
-m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_FALSE])
-m4trace:configure.ac:1153: -1- AM_CONDITIONAL([USE_SLASH_PROC], [test "$os" = "linux"])
-m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_SLASH_PROC_TRUE$])
-m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_SLASH_PROC_FALSE$])
-m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_TRUE])
-m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_FALSE])
-m4trace:configure.ac:1154: -1- AM_CONDITIONAL([USE_PRINTF_WRAPPERS], [test "$bsdPrintfWrappers" = "yes"])
-m4trace:configure.ac:1154: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_TRUE$])
-m4trace:configure.ac:1154: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_FALSE$])
-m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_TRUE])
-m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_FALSE])
-m4trace:configure.ac:1155: -1- AM_CONDITIONAL([ENABLE_DEPLOYPKG], [test "$enable_deploypkg" = "yes"])
-m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_TRUE$])
-m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_FALSE$])
-m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_TRUE])
-m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_FALSE])
-m4trace:configure.ac:1156: -1- AM_CONDITIONAL([ENABLE_GRABBITMQPROXY], [test "$enable_grabbitmqproxy" = "yes"])
-m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_TRUE$])
-m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_FALSE$])
-m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_TRUE])
-m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_FALSE])
-m4trace:configure.ac:1157: -1- AM_CONDITIONAL([ENABLE_VGAUTH], [test "$enable_vgauth" = "yes"])
-m4trace:configure.ac:1157: -1- m4_pattern_allow([^ENABLE_VGAUTH_TRUE$])
-m4trace:configure.ac:1157: -1- m4_pattern_allow([^ENABLE_VGAUTH_FALSE$])
-m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_TRUE])
-m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_FALSE])
-m4trace:configure.ac:1158: -1- AM_CONDITIONAL([HAVE_VSOCK], [test "$os" = "linux"])
-m4trace:configure.ac:1158: -1- m4_pattern_allow([^HAVE_VSOCK_TRUE$])
-m4trace:configure.ac:1158: -1- m4_pattern_allow([^HAVE_VSOCK_FALSE$])
-m4trace:configure.ac:1158: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_TRUE])
-m4trace:configure.ac:1158: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_FALSE])
-m4trace:configure.ac:1161: -1- m4_pattern_allow([^NO_XSM$])
-m4trace:configure.ac:1165: -1- m4_pattern_allow([^NO_XCOMPOSITE$])
-m4trace:configure.ac:1177: -1- m4_pattern_allow([^NO_MULTIMON$])
-m4trace:configure.ac:1219: -1- m4_pattern_allow([^HGFS_LIBS$])
-m4trace:configure.ac:1220: -1- m4_pattern_allow([^TOOLS_VERSION$])
-m4trace:configure.ac:1221: -1- m4_pattern_allow([^TARGET_OS$])
-m4trace:configure.ac:1222: -1- m4_pattern_allow([^KERNEL_RELEASE$])
-m4trace:configure.ac:1223: -1- m4_pattern_allow([^LINUXINCLUDE$])
-m4trace:configure.ac:1224: -1- m4_pattern_allow([^MODULES_OS$])
-m4trace:configure.ac:1225: -1- m4_pattern_allow([^MODULES_DIR$])
-m4trace:configure.ac:1226: -1- m4_pattern_allow([^MODULES$])
-m4trace:configure.ac:1227: -1- m4_pattern_allow([^COMMON_XLIBS$])
-m4trace:configure.ac:1228: -1- m4_pattern_allow([^XSM_LIBS$])
-m4trace:configure.ac:1229: -1- m4_pattern_allow([^XCOMPOSITE_LIBS$])
-m4trace:configure.ac:1230: -1- m4_pattern_allow([^PAM_PREFIX$])
-m4trace:configure.ac:1231: -1- m4_pattern_allow([^PLUGIN_CPPFLAGS$])
-m4trace:configure.ac:1232: -1- m4_pattern_allow([^PLUGIN_LDFLAGS$])
-m4trace:configure.ac:1233: -1- m4_pattern_allow([^VMTOOLS_CPPFLAGS$])
-m4trace:configure.ac:1234: -1- m4_pattern_allow([^VMTOOLS_LIBS$])
-m4trace:configure.ac:1235: -1- m4_pattern_allow([^RPCGENFLAGS$])
-m4trace:configure.ac:1236: -1- m4_pattern_allow([^XDR_LIBS$])
-m4trace:configure.ac:1237: -1- m4_pattern_allow([^TEST_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1238: -1- m4_pattern_allow([^COMMON_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1239: -1- m4_pattern_allow([^VMSVC_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1240: -1- m4_pattern_allow([^VMUSR_PLUGIN_INSTALLDIR$])
-m4trace:configure.ac:1245: -1- m4_pattern_allow([^SYSDIR$])
-m4trace:configure.ac:1247: -1- m4_pattern_allow([^INSTVMSG$])
-m4trace:configure.ac:1248: -1- m4_pattern_allow([^RPCGEN_WRAPPER$])
-m4trace:configure.ac:1252: -1- m4_pattern_allow([^LIB_AUTH_CPPFLAGS$])
-m4trace:configure.ac:1253: -1- m4_pattern_allow([^LIB_IMPERSONATE_CPPFLAGS$])
-m4trace:configure.ac:1254: -1- m4_pattern_allow([^LIB_USER_CPPFLAGS$])
-m4trace:configure.ac:1255: -1- m4_pattern_allow([^LIBVMTOOLS_LIBADD$])
-m4trace:configure.ac:1259: -1- m4_pattern_allow([^VIX_LIBADD$])
-m4trace:configure.ac:1260: -1- m4_pattern_allow([^VGAUTH_LIBADD$])
+m4trace:configure.ac:1132: -1- AM_CONDITIONAL([BUILD_HGFSMOUNTER], [test "$buildHgfsmounter" = "yes"])
+m4trace:configure.ac:1132: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_TRUE$])
+m4trace:configure.ac:1132: -1- m4_pattern_allow([^BUILD_HGFSMOUNTER_FALSE$])
+m4trace:configure.ac:1132: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_TRUE])
+m4trace:configure.ac:1132: -1- _AM_SUBST_NOTMAKE([BUILD_HGFSMOUNTER_FALSE])
+m4trace:configure.ac:1133: -1- AM_CONDITIONAL([LINUX], [test "$os" = "linux"])
+m4trace:configure.ac:1133: -1- m4_pattern_allow([^LINUX_TRUE$])
+m4trace:configure.ac:1133: -1- m4_pattern_allow([^LINUX_FALSE$])
+m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([LINUX_TRUE])
+m4trace:configure.ac:1133: -1- _AM_SUBST_NOTMAKE([LINUX_FALSE])
+m4trace:configure.ac:1134: -1- AM_CONDITIONAL([SOLARIS], [test "$os" = "solaris"])
+m4trace:configure.ac:1134: -1- m4_pattern_allow([^SOLARIS_TRUE$])
+m4trace:configure.ac:1134: -1- m4_pattern_allow([^SOLARIS_FALSE$])
+m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([SOLARIS_TRUE])
+m4trace:configure.ac:1134: -1- _AM_SUBST_NOTMAKE([SOLARIS_FALSE])
+m4trace:configure.ac:1135: -1- AM_CONDITIONAL([FREEBSD], [test "$os" = "freebsd" -o "$os" = "kfreebsd-gnu"])
+m4trace:configure.ac:1135: -1- m4_pattern_allow([^FREEBSD_TRUE$])
+m4trace:configure.ac:1135: -1- m4_pattern_allow([^FREEBSD_FALSE$])
+m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([FREEBSD_TRUE])
+m4trace:configure.ac:1135: -1- _AM_SUBST_NOTMAKE([FREEBSD_FALSE])
+m4trace:configure.ac:1136: -1- AM_CONDITIONAL([FREEBSD_CUSTOM_SYSDIR], [test \( "$os" = "freebsd" -o "$os" = "kfreebsd-gnu" \) -a -n "$SYSDIR"])
+m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_TRUE$])
+m4trace:configure.ac:1136: -1- m4_pattern_allow([^FREEBSD_CUSTOM_SYSDIR_FALSE$])
+m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_TRUE])
+m4trace:configure.ac:1136: -1- _AM_SUBST_NOTMAKE([FREEBSD_CUSTOM_SYSDIR_FALSE])
+m4trace:configure.ac:1138: -1- AM_CONDITIONAL([THIRTY_TWO_BIT_USERSPACE], [test "$userSpaceBitness" = "32"])
+m4trace:configure.ac:1138: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_TRUE$])
+m4trace:configure.ac:1138: -1- m4_pattern_allow([^THIRTY_TWO_BIT_USERSPACE_FALSE$])
+m4trace:configure.ac:1138: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_TRUE])
+m4trace:configure.ac:1138: -1- _AM_SUBST_NOTMAKE([THIRTY_TWO_BIT_USERSPACE_FALSE])
+m4trace:configure.ac:1139: -1- AM_CONDITIONAL([HAVE_X11], [test "$have_x" = "yes"])
+m4trace:configure.ac:1139: -1- m4_pattern_allow([^HAVE_X11_TRUE$])
+m4trace:configure.ac:1139: -1- m4_pattern_allow([^HAVE_X11_FALSE$])
+m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([HAVE_X11_TRUE])
+m4trace:configure.ac:1139: -1- _AM_SUBST_NOTMAKE([HAVE_X11_FALSE])
+m4trace:configure.ac:1140: -1- AM_CONDITIONAL([HAVE_ICU], [test "$with_icu" = "yes"])
+m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_ICU_TRUE$])
+m4trace:configure.ac:1140: -1- m4_pattern_allow([^HAVE_ICU_FALSE$])
+m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_TRUE])
+m4trace:configure.ac:1140: -1- _AM_SUBST_NOTMAKE([HAVE_ICU_FALSE])
+m4trace:configure.ac:1141: -1- AM_CONDITIONAL([WITH_KERNEL_MODULES], [test "$with_kernel_modules" = "yes"])
+m4trace:configure.ac:1141: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_TRUE$])
+m4trace:configure.ac:1141: -1- m4_pattern_allow([^WITH_KERNEL_MODULES_FALSE$])
+m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_TRUE])
+m4trace:configure.ac:1141: -1- _AM_SUBST_NOTMAKE([WITH_KERNEL_MODULES_FALSE])
+m4trace:configure.ac:1142: -1- AM_CONDITIONAL([HAVE_XSM], [test "$have_xsm" = "yes"])
+m4trace:configure.ac:1142: -1- m4_pattern_allow([^HAVE_XSM_TRUE$])
+m4trace:configure.ac:1142: -1- m4_pattern_allow([^HAVE_XSM_FALSE$])
+m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_TRUE])
+m4trace:configure.ac:1142: -1- _AM_SUBST_NOTMAKE([HAVE_XSM_FALSE])
+m4trace:configure.ac:1143: -1- AM_CONDITIONAL([HAVE_XCOMPOSITE], [test "$have_xcomposite" = "yes"])
+m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_TRUE$])
+m4trace:configure.ac:1143: -1- m4_pattern_allow([^HAVE_XCOMPOSITE_FALSE$])
+m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_TRUE])
+m4trace:configure.ac:1143: -1- _AM_SUBST_NOTMAKE([HAVE_XCOMPOSITE_FALSE])
+m4trace:configure.ac:1144: -1- AM_CONDITIONAL([ENABLE_TESTS], [test "$have_cunit" = "yes"])
+m4trace:configure.ac:1144: -1- m4_pattern_allow([^ENABLE_TESTS_TRUE$])
+m4trace:configure.ac:1144: -1- m4_pattern_allow([^ENABLE_TESTS_FALSE$])
+m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_TRUE])
+m4trace:configure.ac:1144: -1- _AM_SUBST_NOTMAKE([ENABLE_TESTS_FALSE])
+m4trace:configure.ac:1145: -1- AM_CONDITIONAL([WITH_ROOT_PRIVILEGES], [test "$with_root_privileges" = "yes"])
+m4trace:configure.ac:1145: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_TRUE$])
+m4trace:configure.ac:1145: -1- m4_pattern_allow([^WITH_ROOT_PRIVILEGES_FALSE$])
+m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_TRUE])
+m4trace:configure.ac:1145: -1- _AM_SUBST_NOTMAKE([WITH_ROOT_PRIVILEGES_FALSE])
+m4trace:configure.ac:1146: -1- AM_CONDITIONAL([HAVE_DNET], [test "$have_dnet" = "yes"])
+m4trace:configure.ac:1146: -1- m4_pattern_allow([^HAVE_DNET_TRUE$])
+m4trace:configure.ac:1146: -1- m4_pattern_allow([^HAVE_DNET_FALSE$])
+m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_TRUE])
+m4trace:configure.ac:1146: -1- _AM_SUBST_NOTMAKE([HAVE_DNET_FALSE])
+m4trace:configure.ac:1147: -1- AM_CONDITIONAL([HAVE_DOXYGEN], [test "$have_doxygen" = "yes"])
+m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DOXYGEN_TRUE$])
+m4trace:configure.ac:1147: -1- m4_pattern_allow([^HAVE_DOXYGEN_FALSE$])
+m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_TRUE])
+m4trace:configure.ac:1147: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_FALSE])
+m4trace:configure.ac:1148: -1- AM_CONDITIONAL([HAVE_FUSE], [test "$have_fuse" = "yes"])
+m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_FUSE_TRUE$])
+m4trace:configure.ac:1148: -1- m4_pattern_allow([^HAVE_FUSE_FALSE$])
+m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_TRUE])
+m4trace:configure.ac:1148: -1- _AM_SUBST_NOTMAKE([HAVE_FUSE_FALSE])
+m4trace:configure.ac:1149: -1- AM_CONDITIONAL([HAVE_GNU_LD], [test "$with_gnu_ld" = "yes"])
+m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_GNU_LD_TRUE$])
+m4trace:configure.ac:1149: -1- m4_pattern_allow([^HAVE_GNU_LD_FALSE$])
+m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_TRUE])
+m4trace:configure.ac:1149: -1- _AM_SUBST_NOTMAKE([HAVE_GNU_LD_FALSE])
+m4trace:configure.ac:1150: -1- AM_CONDITIONAL([HAVE_GTKMM], [test "$have_x" = "yes" -a "$with_gtkmm" = "yes"])
+m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GTKMM_TRUE$])
+m4trace:configure.ac:1150: -1- m4_pattern_allow([^HAVE_GTKMM_FALSE$])
+m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_TRUE])
+m4trace:configure.ac:1150: -1- _AM_SUBST_NOTMAKE([HAVE_GTKMM_FALSE])
+m4trace:configure.ac:1151: -1- AM_CONDITIONAL([HAVE_PAM], [test "$with_pam" = "yes"])
+m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_PAM_TRUE$])
+m4trace:configure.ac:1151: -1- m4_pattern_allow([^HAVE_PAM_FALSE$])
+m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_TRUE])
+m4trace:configure.ac:1151: -1- _AM_SUBST_NOTMAKE([HAVE_PAM_FALSE])
+m4trace:configure.ac:1152: -1- AM_CONDITIONAL([USE_SLASH_PROC], [test "$os" = "linux"])
+m4trace:configure.ac:1152: -1- m4_pattern_allow([^USE_SLASH_PROC_TRUE$])
+m4trace:configure.ac:1152: -1- m4_pattern_allow([^USE_SLASH_PROC_FALSE$])
+m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_TRUE])
+m4trace:configure.ac:1152: -1- _AM_SUBST_NOTMAKE([USE_SLASH_PROC_FALSE])
+m4trace:configure.ac:1153: -1- AM_CONDITIONAL([USE_PRINTF_WRAPPERS], [test "$bsdPrintfWrappers" = "yes"])
+m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_TRUE$])
+m4trace:configure.ac:1153: -1- m4_pattern_allow([^USE_PRINTF_WRAPPERS_FALSE$])
+m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_TRUE])
+m4trace:configure.ac:1153: -1- _AM_SUBST_NOTMAKE([USE_PRINTF_WRAPPERS_FALSE])
+m4trace:configure.ac:1154: -1- AM_CONDITIONAL([ENABLE_DEPLOYPKG], [test "$enable_deploypkg" = "yes"])
+m4trace:configure.ac:1154: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_TRUE$])
+m4trace:configure.ac:1154: -1- m4_pattern_allow([^ENABLE_DEPLOYPKG_FALSE$])
+m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_TRUE])
+m4trace:configure.ac:1154: -1- _AM_SUBST_NOTMAKE([ENABLE_DEPLOYPKG_FALSE])
+m4trace:configure.ac:1155: -1- AM_CONDITIONAL([ENABLE_GRABBITMQPROXY], [test "$enable_grabbitmqproxy" = "yes"])
+m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_TRUE$])
+m4trace:configure.ac:1155: -1- m4_pattern_allow([^ENABLE_GRABBITMQPROXY_FALSE$])
+m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_TRUE])
+m4trace:configure.ac:1155: -1- _AM_SUBST_NOTMAKE([ENABLE_GRABBITMQPROXY_FALSE])
+m4trace:configure.ac:1156: -1- AM_CONDITIONAL([ENABLE_VGAUTH], [test "$enable_vgauth" = "yes"])
+m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_VGAUTH_TRUE$])
+m4trace:configure.ac:1156: -1- m4_pattern_allow([^ENABLE_VGAUTH_FALSE$])
+m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_TRUE])
+m4trace:configure.ac:1156: -1- _AM_SUBST_NOTMAKE([ENABLE_VGAUTH_FALSE])
+m4trace:configure.ac:1157: -1- AM_CONDITIONAL([HAVE_VSOCK], [test "$os" = "linux"])
+m4trace:configure.ac:1157: -1- m4_pattern_allow([^HAVE_VSOCK_TRUE$])
+m4trace:configure.ac:1157: -1- m4_pattern_allow([^HAVE_VSOCK_FALSE$])
+m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_TRUE])
+m4trace:configure.ac:1157: -1- _AM_SUBST_NOTMAKE([HAVE_VSOCK_FALSE])
+m4trace:configure.ac:1160: -1- m4_pattern_allow([^NO_XSM$])
+m4trace:configure.ac:1164: -1- m4_pattern_allow([^NO_XCOMPOSITE$])
+m4trace:configure.ac:1176: -1- m4_pattern_allow([^NO_MULTIMON$])
+m4trace:configure.ac:1218: -1- m4_pattern_allow([^HGFS_LIBS$])
+m4trace:configure.ac:1219: -1- m4_pattern_allow([^TOOLS_VERSION$])
+m4trace:configure.ac:1220: -1- m4_pattern_allow([^TARGET_OS$])
+m4trace:configure.ac:1221: -1- m4_pattern_allow([^KERNEL_RELEASE$])
+m4trace:configure.ac:1222: -1- m4_pattern_allow([^LINUXINCLUDE$])
+m4trace:configure.ac:1223: -1- m4_pattern_allow([^MODULES_OS$])
+m4trace:configure.ac:1224: -1- m4_pattern_allow([^MODULES_DIR$])
+m4trace:configure.ac:1225: -1- m4_pattern_allow([^MODULES$])
+m4trace:configure.ac:1226: -1- m4_pattern_allow([^COMMON_XLIBS$])
+m4trace:configure.ac:1227: -1- m4_pattern_allow([^XSM_LIBS$])
+m4trace:configure.ac:1228: -1- m4_pattern_allow([^XCOMPOSITE_LIBS$])
+m4trace:configure.ac:1229: -1- m4_pattern_allow([^PAM_PREFIX$])
+m4trace:configure.ac:1230: -1- m4_pattern_allow([^PLUGIN_CPPFLAGS$])
+m4trace:configure.ac:1231: -1- m4_pattern_allow([^PLUGIN_LDFLAGS$])
+m4trace:configure.ac:1232: -1- m4_pattern_allow([^VMTOOLS_CPPFLAGS$])
+m4trace:configure.ac:1233: -1- m4_pattern_allow([^VMTOOLS_LIBS$])
+m4trace:configure.ac:1234: -1- m4_pattern_allow([^RPCGENFLAGS$])
+m4trace:configure.ac:1235: -1- m4_pattern_allow([^XDR_LIBS$])
+m4trace:configure.ac:1236: -1- m4_pattern_allow([^TEST_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1237: -1- m4_pattern_allow([^COMMON_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1238: -1- m4_pattern_allow([^VMSVC_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1239: -1- m4_pattern_allow([^VMUSR_PLUGIN_INSTALLDIR$])
+m4trace:configure.ac:1244: -1- m4_pattern_allow([^SYSDIR$])
+m4trace:configure.ac:1246: -1- m4_pattern_allow([^INSTVMSG$])
+m4trace:configure.ac:1247: -1- m4_pattern_allow([^RPCGEN_WRAPPER$])
+m4trace:configure.ac:1251: -1- m4_pattern_allow([^LIB_AUTH_CPPFLAGS$])
+m4trace:configure.ac:1252: -1- m4_pattern_allow([^LIB_IMPERSONATE_CPPFLAGS$])
+m4trace:configure.ac:1253: -1- m4_pattern_allow([^LIB_USER_CPPFLAGS$])
+m4trace:configure.ac:1254: -1- m4_pattern_allow([^LIBVMTOOLS_LIBADD$])
+m4trace:configure.ac:1258: -1- m4_pattern_allow([^VIX_LIBADD$])
+m4trace:configure.ac:1259: -1- m4_pattern_allow([^VGAUTH_LIBADD$])
m4trace:configure.ac:1365: -1- m4_pattern_allow([^LIB@&t@OBJS$])
m4trace:configure.ac:1365: -1- m4_pattern_allow([^LTLIBOBJS$])
m4trace:configure.ac:1365: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS
diff --git a/open-vm-tools/configure b/open-vm-tools/configure
index 1a60f630..f2724783 100644..100755
--- a/open-vm-tools/configure
+++ b/open-vm-tools/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for open-vm-tools 9.10.2.
+# Generated by GNU Autoconf 2.61 for open-vm-tools 10.0.0.
#
# Report bugs to <open-vm-tools-devel@lists.sourceforge.net>.
#
@@ -723,8 +723,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='open-vm-tools'
PACKAGE_TARNAME='open-vm-tools'
-PACKAGE_VERSION='9.10.2'
-PACKAGE_STRING='open-vm-tools 9.10.2'
+PACKAGE_VERSION='10.0.0'
+PACKAGE_STRING='open-vm-tools 10.0.0'
PACKAGE_BUGREPORT='open-vm-tools-devel@lists.sourceforge.net'
ac_unique_file="checkvm/checkvm.c"
@@ -1517,7 +1517,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures open-vm-tools 9.10.2 to adapt to many kinds of systems.
+\`configure' configures open-vm-tools 10.0.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1591,7 +1591,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of open-vm-tools 9.10.2:";;
+ short | recursive ) echo "Configuration of open-vm-tools 10.0.0:";;
esac
cat <<\_ACEOF
@@ -1723,7 +1723,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-open-vm-tools configure 9.10.2
+open-vm-tools configure 10.0.0
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1737,7 +1737,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by open-vm-tools $as_me 9.10.2, which was
+It was created by open-vm-tools $as_me 10.0.0, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2744,7 +2744,7 @@ fi
# Define the identity of the package.
PACKAGE='open-vm-tools'
- VERSION='9.10.2'
+ VERSION='10.0.0'
cat >>confdefs.h <<_ACEOF
@@ -20000,8 +20000,8 @@ fi
else
true
have_fuse=no;
- { echo "$as_me:$LINENO: WARNING: Fuse is missing, vmblock-fuse will be disabled." >&5
-echo "$as_me: WARNING: Fuse is missing, vmblock-fuse will be disabled." >&2;}
+ { echo "$as_me:$LINENO: WARNING: Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled." >&5
+echo "$as_me: WARNING: Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled." >&2;}
fi
@@ -30816,15 +30816,14 @@ if test "$os" = "linux"; then
LIBVMTOOLS_LIBADD="$LIBVMTOOLS_LIBADD -lrt"
- # vmhgfs is not compiled for kernels 3.17 and newer
- # Temporary short term limit until the newer kernel component is included
- if test "$osVersion" -lt 317000; then
- MODULES="$MODULES vmhgfs"
- fi
# vmxnet is not supported for kernels 3.3.0 and newer
if test "$osVersion" -lt 303000; then
MODULES="$MODULES vmxnet"
fi
+ # See if we need vmhgfs module. Starting with 4.0.0 we use FUSE
+ if test "$osVersion" -lt 400000; then
+ MODULES="$MODULES vmhgfs"
+ fi
# See if we need vmci and vsock modules. Starting with 3.9 they made
# their way into mainline kernel.
if test "$osVersion" -lt 309000; then
@@ -31351,7 +31350,7 @@ fi
###
### Create the Makefiles
###
-ac_config_files="$ac_config_files Makefile lib/Makefile lib/appUtil/Makefile lib/auth/Makefile lib/backdoor/Makefile lib/asyncsocket/Makefile lib/sslDirect/Makefile lib/pollGtk/Makefile lib/poll/Makefile lib/dataMap/Makefile lib/hashMap/Makefile lib/dict/Makefile lib/dynxdr/Makefile lib/err/Makefile lib/file/Makefile lib/foundryMsg/Makefile lib/glibUtils/Makefile lib/guestApp/Makefile lib/guestRpc/Makefile lib/hgfs/Makefile lib/hgfsBd/Makefile lib/hgfsHelper/Makefile lib/hgfsServer/Makefile lib/hgfsServerManagerGuest/Makefile lib/hgfsServerPolicyGuest/Makefile lib/impersonate/Makefile lib/lock/Makefile lib/message/Makefile lib/misc/Makefile lib/netUtil/Makefile lib/nicInfo/Makefile lib/panic/Makefile lib/panicDefault/Makefile lib/printer/Makefile lib/procMgr/Makefile lib/rpcChannel/Makefile lib/rpcIn/Makefile lib/rpcOut/Makefile lib/rpcVmx/Makefile lib/slashProc/Makefile lib/string/Makefile lib/stubs/Makefile lib/syncDriver/Makefile lib/system/Makefile lib/unicode/Makefile lib/user/Makefile lib/vmCheck/Makefile lib/vmSignal/Makefile lib/wiper/Makefile lib/xdg/Makefile services/Makefile services/vmtoolsd/Makefile services/plugins/Makefile services/plugins/desktopEvents/Makefile services/plugins/dndcp/Makefile services/plugins/grabbitmqProxy/Makefile services/plugins/guestInfo/Makefile services/plugins/hgfsServer/Makefile services/plugins/powerOps/Makefile services/plugins/resolutionSet/Makefile services/plugins/timeSync/Makefile services/plugins/vix/Makefile services/plugins/vmbackup/Makefile services/plugins/deployPkg/Makefile vmware-user-suid-wrapper/Makefile toolbox/Makefile hgfsclient/Makefile hgfsmounter/Makefile checkvm/Makefile rpctool/Makefile guestproxycerttool/Makefile vgauth/Makefile vgauth/lib/Makefile vgauth/cli/Makefile vgauth/service/Makefile libguestlib/Makefile libguestlib/vmguestlib.pc libDeployPkg/Makefile libDeployPkg/libDeployPkg.pc libhgfs/Makefile libvmtools/Makefile xferlogs/Makefile modules/Makefile vmblock-fuse/Makefile vmblockmounter/Makefile tests/Makefile tests/vmrpcdbg/Makefile tests/testDebug/Makefile tests/testPlugin/Makefile tests/testVmblock/Makefile docs/Makefile docs/api/Makefile scripts/Makefile scripts/build/rpcgen_wrapper.sh"
+ac_config_files="$ac_config_files Makefile lib/Makefile lib/appUtil/Makefile lib/auth/Makefile lib/backdoor/Makefile lib/asyncsocket/Makefile lib/sslDirect/Makefile lib/pollGtk/Makefile lib/poll/Makefile lib/dataMap/Makefile lib/hashMap/Makefile lib/dict/Makefile lib/dynxdr/Makefile lib/err/Makefile lib/file/Makefile lib/foundryMsg/Makefile lib/glibUtils/Makefile lib/guestApp/Makefile lib/guestRpc/Makefile lib/hgfs/Makefile lib/hgfsBd/Makefile lib/hgfsHelper/Makefile lib/hgfsServer/Makefile lib/hgfsServerManagerGuest/Makefile lib/hgfsServerPolicyGuest/Makefile lib/hgfsUri/Makefile lib/impersonate/Makefile lib/lock/Makefile lib/message/Makefile lib/misc/Makefile lib/netUtil/Makefile lib/nicInfo/Makefile lib/panic/Makefile lib/panicDefault/Makefile lib/procMgr/Makefile lib/rpcChannel/Makefile lib/rpcIn/Makefile lib/rpcOut/Makefile lib/rpcVmx/Makefile lib/slashProc/Makefile lib/string/Makefile lib/stubs/Makefile lib/syncDriver/Makefile lib/system/Makefile lib/unicode/Makefile lib/user/Makefile lib/vmCheck/Makefile lib/vmSignal/Makefile lib/wiper/Makefile lib/xdg/Makefile services/Makefile services/vmtoolsd/Makefile services/plugins/Makefile services/plugins/desktopEvents/Makefile services/plugins/dndcp/Makefile services/plugins/grabbitmqProxy/Makefile services/plugins/guestInfo/Makefile services/plugins/hgfsServer/Makefile services/plugins/powerOps/Makefile services/plugins/resolutionSet/Makefile services/plugins/timeSync/Makefile services/plugins/vix/Makefile services/plugins/vmbackup/Makefile services/plugins/deployPkg/Makefile vmware-user-suid-wrapper/Makefile toolbox/Makefile hgfsclient/Makefile hgfsmounter/Makefile checkvm/Makefile rpctool/Makefile guestproxycerttool/Makefile vgauth/Makefile vgauth/lib/Makefile vgauth/cli/Makefile vgauth/service/Makefile libguestlib/Makefile libguestlib/vmguestlib.pc libDeployPkg/Makefile libDeployPkg/libDeployPkg.pc libhgfs/Makefile libvmtools/Makefile xferlogs/Makefile modules/Makefile vmblock-fuse/Makefile vmhgfs-fuse/Makefile vmblockmounter/Makefile tests/Makefile tests/vmrpcdbg/Makefile tests/testDebug/Makefile tests/testPlugin/Makefile tests/testVmblock/Makefile docs/Makefile docs/api/Makefile scripts/Makefile scripts/build/rpcgen_wrapper.sh"
###
@@ -31993,7 +31992,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by open-vm-tools $as_me 9.10.2, which was
+This file was extended by open-vm-tools $as_me 10.0.0, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -32040,7 +32039,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-open-vm-tools config.status 9.10.2
+open-vm-tools config.status 10.0.0
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
@@ -32515,6 +32514,7 @@ do
"lib/hgfsServer/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServer/Makefile" ;;
"lib/hgfsServerManagerGuest/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServerManagerGuest/Makefile" ;;
"lib/hgfsServerPolicyGuest/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsServerPolicyGuest/Makefile" ;;
+ "lib/hgfsUri/Makefile") CONFIG_FILES="$CONFIG_FILES lib/hgfsUri/Makefile" ;;
"lib/impersonate/Makefile") CONFIG_FILES="$CONFIG_FILES lib/impersonate/Makefile" ;;
"lib/lock/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lock/Makefile" ;;
"lib/message/Makefile") CONFIG_FILES="$CONFIG_FILES lib/message/Makefile" ;;
@@ -32523,7 +32523,6 @@ do
"lib/nicInfo/Makefile") CONFIG_FILES="$CONFIG_FILES lib/nicInfo/Makefile" ;;
"lib/panic/Makefile") CONFIG_FILES="$CONFIG_FILES lib/panic/Makefile" ;;
"lib/panicDefault/Makefile") CONFIG_FILES="$CONFIG_FILES lib/panicDefault/Makefile" ;;
- "lib/printer/Makefile") CONFIG_FILES="$CONFIG_FILES lib/printer/Makefile" ;;
"lib/procMgr/Makefile") CONFIG_FILES="$CONFIG_FILES lib/procMgr/Makefile" ;;
"lib/rpcChannel/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpcChannel/Makefile" ;;
"lib/rpcIn/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpcIn/Makefile" ;;
@@ -32574,6 +32573,7 @@ do
"xferlogs/Makefile") CONFIG_FILES="$CONFIG_FILES xferlogs/Makefile" ;;
"modules/Makefile") CONFIG_FILES="$CONFIG_FILES modules/Makefile" ;;
"vmblock-fuse/Makefile") CONFIG_FILES="$CONFIG_FILES vmblock-fuse/Makefile" ;;
+ "vmhgfs-fuse/Makefile") CONFIG_FILES="$CONFIG_FILES vmhgfs-fuse/Makefile" ;;
"vmblockmounter/Makefile") CONFIG_FILES="$CONFIG_FILES vmblockmounter/Makefile" ;;
"tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
"tests/vmrpcdbg/Makefile") CONFIG_FILES="$CONFIG_FILES tests/vmrpcdbg/Makefile" ;;
diff --git a/open-vm-tools/configure.ac b/open-vm-tools/configure.ac
index 6a60d2ab..ebdf17ce 100644
--- a/open-vm-tools/configure.ac
+++ b/open-vm-tools/configure.ac
@@ -39,10 +39,10 @@
### Initialization
###
-TOOLS_VERSION="9.10.2"
+TOOLS_VERSION="10.0.0"
AC_INIT(
[open-vm-tools],
- [9.10.2],
+ [10.0.0],
[open-vm-tools-devel@lists.sourceforge.net])
# In order to make this configure script auto-detect situations where
@@ -377,7 +377,7 @@ AC_VMW_CHECK_LIB([fuse],
[fuse_main],
[have_fuse=yes],
[have_fuse=no;
- AC_MSG_WARN([Fuse is missing, vmblock-fuse will be disabled.])])
+ AC_MSG_WARN([Fuse is missing, vmblock-fuse/vmhgfs-fuse will be disabled.])])
#
# Check for PAM.
@@ -1045,15 +1045,14 @@ if test "$os" = "linux"; then
LIBVMTOOLS_LIBADD="$LIBVMTOOLS_LIBADD -lrt"
- # vmhgfs is not compiled for kernels 3.17 and newer
- # Temporary short term limit until the newer kernel component is included
- if test "$osVersion" -lt 317000; then
- MODULES="$MODULES vmhgfs"
- fi
# vmxnet is not supported for kernels 3.3.0 and newer
if test "$osVersion" -lt 303000; then
MODULES="$MODULES vmxnet"
fi
+ # See if we need vmhgfs module. Starting with 4.0.0 we use FUSE
+ if test "$osVersion" -lt 400000; then
+ MODULES="$MODULES vmhgfs"
+ fi
# See if we need vmci and vsock modules. Starting with 3.9 they made
# their way into mainline kernel.
if test "$osVersion" -lt 309000; then
@@ -1288,6 +1287,7 @@ AC_CONFIG_FILES([ \
lib/hgfsServer/Makefile \
lib/hgfsServerManagerGuest/Makefile \
lib/hgfsServerPolicyGuest/Makefile \
+ lib/hgfsUri/Makefile \
lib/impersonate/Makefile \
lib/lock/Makefile \
lib/message/Makefile \
@@ -1296,7 +1296,6 @@ AC_CONFIG_FILES([ \
lib/nicInfo/Makefile \
lib/panic/Makefile \
lib/panicDefault/Makefile \
- lib/printer/Makefile \
lib/procMgr/Makefile \
lib/rpcChannel/Makefile \
lib/rpcIn/Makefile \
@@ -1347,6 +1346,7 @@ AC_CONFIG_FILES([ \
xferlogs/Makefile \
modules/Makefile \
vmblock-fuse/Makefile \
+ vmhgfs-fuse/Makefile \
vmblockmounter/Makefile \
tests/Makefile \
tests/vmrpcdbg/Makefile \
diff --git a/open-vm-tools/guestproxycerttool/cert_key.c b/open-vm-tools/guestproxycerttool/cert_key.c
index f93047a8..4b0ed8bb 100644
--- a/open-vm-tools/guestproxycerttool/cert_key.c
+++ b/open-vm-tools/guestproxycerttool/cert_key.c
@@ -55,7 +55,7 @@
*----------------------------------------------------------------------
*/
-static gchar *
+gchar *
GetSSLError(gchar **errorStr) // OUT
{
unsigned long code;
@@ -582,6 +582,8 @@ exit:
return cert;
}
+
+#ifndef _WIN32
/*
*----------------------------------------------------------------------
*
@@ -598,7 +600,7 @@ exit:
*----------------------------------------------------------------------
*/
-static gboolean
+gboolean
WritePemFile(EVP_PKEY *pkey, // IN
const gchar *keyFile, // IN
X509 *cert, // IN
@@ -648,6 +650,8 @@ exit:
return ret;
}
+#endif
+
/*
*----------------------------------------------------------------------
diff --git a/open-vm-tools/guestproxycerttool/cert_key.h b/open-vm-tools/guestproxycerttool/cert_key.h
index 7df1aeb9..d05803fb 100644
--- a/open-vm-tools/guestproxycerttool/cert_key.h
+++ b/open-vm-tools/guestproxycerttool/cert_key.h
@@ -21,6 +21,7 @@
#include <glib.h>
#include <glib/gstdio.h>
+#include <openssl/evp.h>
gchar *
CertKey_ComputeCertPemFileHash(const gchar *certPemFile); // IN
@@ -35,4 +36,12 @@ CertKey_GenerateKeyCert(int bits, // IN
void
CertKey_InitOpenSSLLib(void);
+gboolean
+WritePemFile(EVP_PKEY *pkey, // IN
+ const gchar *keyFile, // IN
+ X509 *cert, // IN
+ const gchar *certFile); // IN
+
+gchar *
+GetSSLError(gchar **errorStr); // OUT
#endif // #ifndef _CERT_KEY_H_
diff --git a/open-vm-tools/guestproxycerttool/cert_tool.c b/open-vm-tools/guestproxycerttool/cert_tool.c
index 3ae3dd58..cbc9f021 100644
--- a/open-vm-tools/guestproxycerttool/cert_tool.c
+++ b/open-vm-tools/guestproxycerttool/cert_tool.c
@@ -17,7 +17,7 @@
*********************************************************/
/*
- * guestproxycerttool.c --
+ * cert_tool.c --
*
* Utility to manage the certificates for 'rabbitmqproxy'
* plugin in 'VMware Tools'.
@@ -27,11 +27,16 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#ifndef _WIN32
#include <unistd.h>
+#endif
#include <sys/types.h>
#include "cert_util.h"
#include "cert_key.h"
#include "cert_tool_version.h"
+#ifdef _WIN32
+#include "common_win.h"
+#endif
#include "vm_version.h"
#include "embed_version.h"
@@ -51,6 +56,9 @@ static gchar *guestProxySslConf;
#define RSA_KEY_LENGTH 2048
#define CERT_EXPIRED_IN_DAYS (365 * 10)
+
+gboolean gIsLogEnabled = FALSE;
+
/*
*----------------------------------------------------------------------
*
@@ -73,14 +81,17 @@ PrintUsage(const gchar *cmd) // IN
fprintf(stderr, "Guest Proxy Certificate Management Tool.\n");
fprintf(stderr, "Usage: %s [OPTION] [ARGUMENTS]\n\n", cmd);
fprintf(stderr, "Options\n"
- " -h, --help Prints the Usage information.\n\n"
- " -g, --generate_key_cert Regenerate the server key/cert, the old\n"
- " key/cert will be replaced.\n\n"
+ " -h, --help Prints the usage information.\n\n"
+ " -v, --verbose Prints additional log messages.\n\n"
+ " -f, --force Forces to regenerate the new server key/cert\n"
+ " when used with -g.\n\n"
+ " -g, --generate_key_cert Generates the server key/cert if they don't\n"
+ " exist. Use with -f to force the regeneration.\n\n"
" -a, --add_trust_cert <client_cert_pem_file>\n"
" Adds the client cert to the trusted\n"
" certificates directory.\n\n"
" -r, --remove_trust_cert <client_cert_pem_file>\n"
- " Remove the client cert from the trusted\n"
+ " Removes the client cert from the trusted\n"
" certificates directory.\n\n"
" -d, --display_server_cert [<cert_pem_file>]\n"
" Prints the server's certificate to the\n"
@@ -90,6 +101,46 @@ PrintUsage(const gchar *cmd) // IN
}
+static void
+InitProxyPaths(const gchar *toolDir)
+{
+ guestProxyDir = g_build_filename(toolDir, "GuestProxyData", NULL);
+ guestProxyServerDir = g_build_filename(guestProxyDir, "server", NULL);
+ guestProxyTrustedDir = g_build_filename(guestProxyDir, "trusted", NULL);
+ guestProxySslConf = g_build_filename(toolDir, "guestproxy-ssl.conf", NULL);
+}
+
+
+#ifndef _WIN32
+/*
+ *----------------------------------------------------------------------
+ *
+ * CheckRootPriv --
+ *
+ * Check if the effect user id is root.
+ *
+ * Results:
+ * TRUE if it is, otherwise FALSE.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+gboolean
+CheckRootPriv(void)
+{
+ if (geteuid() != 0) {
+ Error("Please re-run this program as the super user to execute "
+ "this operation.\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif
+
+
/*
*----------------------------------------------------------------------
*
@@ -102,8 +153,8 @@ PrintUsage(const gchar *cmd) // IN
* TRUE if successfully find all the paths. Otherwise FALSE.
*
* Side effects:
- * Path global variables are set accordingly and initialized is set
- * to true so it is only initialized once.
+ * Path global variables are set accordingly and guest proxy data
+ * directories are created on-demand.
*
*----------------------------------------------------------------------
*/
@@ -113,50 +164,45 @@ ValidateEnvironment(gboolean requireRootPriv) // IN
{
gboolean ret = FALSE;
- if (requireRootPriv && geteuid() != 0) {
- Error("Please re-run this program as the super user to execute "
- "this operation.\n");
+ if (requireRootPriv && !CheckRootPriv()) {
+ Error("Current user has insufficient privileges.\n");
goto exit;
}
- ret = initialized;
- if (ret) {
- goto exit;
+ if (!initialized) {
+ CertKey_InitOpenSSLLib();
+ initialized = TRUE;
}
- CertKey_InitOpenSSLLib();
+ if (!g_file_test(guestProxySslConf, G_FILE_TEST_IS_REGULAR)) {
+ Error("Couldn't find the GuestProxy Config file at '%s'.\n",
+ guestProxySslConf);
+ goto exit;
+ }
- guestProxyDir = g_build_filename(CertUtil_GetToolDir(),
- "GuestProxyData", NULL);
+ /* Create guest proxy data directories on-demand */
if (!g_file_test(guestProxyDir, G_FILE_TEST_IS_DIR)) {
- Error("Couldn't find the GuestProxy Directory at '%s'.\n",
- guestProxyDir);
- goto exit;
+ if (g_mkdir(guestProxyDir, 0755) < 0) {
+ Error("Couldn't create the directory '%s'.\n", guestProxyDir);
+ goto exit;
+ }
}
- guestProxyServerDir = g_build_filename(guestProxyDir, "server", NULL);
if (!g_file_test(guestProxyServerDir, G_FILE_TEST_IS_DIR)) {
- Error("Couldn't find the GuestProxy Certificate Directory at '%s'.\n",
- guestProxyServerDir);
- goto exit;
+ if (g_mkdir(guestProxyServerDir, 0755) < 0) {
+ Error("Couldn't create the directory '%s'.\n", guestProxyServerDir);
+ goto exit;
+ }
}
- guestProxyTrustedDir = g_build_filename(guestProxyDir, "trusted", NULL);
if (!g_file_test(guestProxyTrustedDir, G_FILE_TEST_IS_DIR)) {
- Error("Couldn't find the GuestProxy Certificate Store at '%s'.\n",
- guestProxyTrustedDir);
- goto exit;
- }
-
- guestProxySslConf = g_build_filename(CertUtil_GetToolDir(),
- "guestproxy-ssl.conf", NULL);
- if (!g_file_test(guestProxySslConf, G_FILE_TEST_IS_REGULAR)) {
- Error("Couldn't find the GuestProxy Config file at '%s'.\n",
- guestProxySslConf);
- goto exit;
+ if (g_mkdir(guestProxyTrustedDir, 0700) < 0) {
+ Error("Couldn't create the directory '%s'.\n", guestProxyTrustedDir);
+ goto exit;
+ }
}
- initialized = ret = TRUE;
+ ret = TRUE;
exit:
return ret;
@@ -322,7 +368,7 @@ exit:
*/
static gboolean
-CreateKeyCert(void)
+CreateKeyCert(gboolean force)
{
gboolean ret = FALSE;
gchar *cert = NULL;
@@ -335,6 +381,21 @@ CreateKeyCert(void)
key = g_build_filename(guestProxyServerDir, "key.pem", NULL);
cert = g_build_filename(guestProxyServerDir, "cert.pem", NULL);
+ /*
+ * If both server key and certificate files already exist and the
+ * program is not asked to create them by force, print an warning
+ * message about server key/cert files not regenerating.
+ */
+ if (g_file_test(key, G_FILE_TEST_IS_REGULAR) &&
+ g_file_test(cert, G_FILE_TEST_IS_REGULAR) && !force) {
+ printf("\nNOTE: both %s and \n %s already exist.\n"
+ " They are not generated again. To regenerate "
+ "them by force,\n use the \"%s -g -f\" command.\n\n",
+ key, cert, g_get_prgname());
+ ret = TRUE;
+ goto exit;
+ }
+
printf("Generating the key and certificate files.\n");
if (!CertKey_GenerateKeyCert(RSA_KEY_LENGTH, CERT_EXPIRED_IN_DAYS,
@@ -427,6 +488,50 @@ exit:
/*
+ " -e, --erase_proxy_data Erases the trusted and server directories,\n"
+ " and their contents including server key/cert.\n\n"
+*/
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EraseProxyData --
+ *
+ * Delete the guest proxy data diectory and its contents.
+ *
+ * Results:
+ * TRUE if success, otherwise FALSE.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static gboolean
+EraseProxyData(void)
+{
+ gboolean ret = FALSE;
+
+ if (!CheckRootPriv()) {
+ goto exit;
+ }
+
+ if (g_file_test(guestProxyDir, G_FILE_TEST_IS_DIR)) {
+ if (!CertUtil_RemoveDir(guestProxyDir)) {
+ Error("Fail to remove the directory '%s'.\n", guestProxyDir);
+ goto exit;
+ }
+ }
+
+ ret = TRUE;
+
+exit:
+ return ret;
+}
+
+
+/*
* Aggregation of command options.
*/
static struct _options {
@@ -436,7 +541,10 @@ static struct _options {
gboolean displayCert;
gboolean generateCert;
gboolean usage;
-} options = { NULL, NULL, NULL, FALSE, FALSE, FALSE};
+ gboolean verbose;
+ gboolean force;
+ gboolean erase;
+} options = { NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE};
static gboolean
@@ -457,6 +565,12 @@ ParseDisplayCert(const gchar* name,
static GOptionEntry cmdOptions[] = {
{ "help", 'h', 0,
G_OPTION_ARG_NONE, &options.usage, NULL, NULL },
+ { "verbose", 'v', 0,
+ G_OPTION_ARG_NONE, &options.verbose, NULL, NULL },
+ { "erase_proxy_data", 'e', 0,
+ G_OPTION_ARG_NONE, &options.erase, NULL, NULL },
+ { "force", 'f', 0,
+ G_OPTION_ARG_NONE, &options.force, NULL, NULL },
{ "generate_key_cert", 'g', 0,
G_OPTION_ARG_NONE, &options.generateCert, NULL, NULL },
{ "add_trust_cert", 'a', 0,
@@ -520,10 +634,17 @@ main(int argc, char **argv)
exit(0);
}
- if ((options.generateCert && !CreateKeyCert()) ||
+ if (options.verbose) {
+ gIsLogEnabled = TRUE;
+ }
+
+ InitProxyPaths(CertUtil_GetToolDir());
+
+ if ((options.generateCert && !CreateKeyCert(options.force)) ||
(options.displayCert && !DisplayServerCert(options.outputCert)) ||
(options.addCert && !AddTrustCert(options.addCert)) ||
- (options.deleteCert && !RemoveTrustCert(options.deleteCert))) {
+ (options.deleteCert && !RemoveTrustCert(options.deleteCert)) ||
+ (options.erase && !EraseProxyData())) {
return 1;
} else {
return 0;
diff --git a/open-vm-tools/guestproxycerttool/cert_util.c b/open-vm-tools/guestproxycerttool/cert_util.c
index ae0e4785..e268f6c4 100644
--- a/open-vm-tools/guestproxycerttool/cert_util.c
+++ b/open-vm-tools/guestproxycerttool/cert_util.c
@@ -17,7 +17,7 @@
*********************************************************/
/*
- * certUtil.c --
+ * cert_util.c --
*
* Utilities to manage the certificates.
*/
@@ -336,6 +336,7 @@ exit:
}
+#ifndef _WIN32
/*
*----------------------------------------------------------------------
*
@@ -364,6 +365,7 @@ CertUtil_GetToolDir(void)
return path;
}
+#endif
/*
@@ -425,3 +427,70 @@ exit:
return ret;
}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CertUtil_RemoveDir --
+ *
+ * Remove a directory. This directory can be non-empty. When it is
+ * non-empty, all of its files and subdirectories are removed too.
+ *
+ * Results:
+ * TRUE if the directory is successfully removed, otherwise FALSE.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+gboolean
+CertUtil_RemoveDir(const gchar *dirToRemove)
+{
+ gboolean ret = FALSE;
+ GDir *dir = NULL;
+ const gchar *file;
+ GError *error = NULL;
+ gchar *fname = NULL;
+
+ if ((dir = g_dir_open(dirToRemove, 0, &error)) == NULL) {
+ Error("Failed to open %s: %s.\n", dirToRemove, error->message);
+ goto exit;
+ }
+
+ while ((file = g_dir_read_name(dir)) != NULL) {
+ g_free(fname);
+ fname = g_build_filename(dirToRemove, file, NULL);
+
+ if (g_file_test(fname, G_FILE_TEST_IS_DIR)) {
+ if (!CertUtil_RemoveDir(fname)) {
+ Error("Couldn't remove the directory '%s'.\n", fname);
+ goto exit;
+ }
+ } else if (g_remove(fname) < 0) {
+ Error("Couldn't remove the file '%s'.\n", fname);
+ goto exit;
+ }
+ }
+
+ g_dir_close(dir);
+ dir = NULL;
+
+ if (g_rmdir(dirToRemove) < 0) {
+ Error("Couldn't remove the directory '%s'.\n", dirToRemove);
+ goto exit;
+ }
+
+ ret = TRUE;
+
+exit:
+ g_free(fname);
+ g_clear_error(&error);
+ if (dir) {
+ g_dir_close(dir);
+ }
+
+ return ret;
+}
diff --git a/open-vm-tools/guestproxycerttool/cert_util.h b/open-vm-tools/guestproxycerttool/cert_util.h
index a5806f63..b9c52368 100644
--- a/open-vm-tools/guestproxycerttool/cert_util.h
+++ b/open-vm-tools/guestproxycerttool/cert_util.h
@@ -39,8 +39,13 @@
*----------------------------------------------------------------------
*/
+#ifdef _WIN32
+#define Error(fmt, ...) \
+ fprintf(stderr, "%s: " fmt, g_get_prgname(), __VA_ARGS__);
+#else
#define Error(fmt, args...) \
fprintf(stderr, "%s: " fmt, g_get_prgname(), ##args);
+#endif
gchar *
CertUtil_CreateCertFileName(const gchar *certDir, // IN
@@ -58,6 +63,11 @@ gboolean
CertUtil_CopyFile(const gchar *src, // IN
const gchar *dst); // IN
+gboolean
+CertUtil_RemoveDir(const gchar *dirToRemove); // IN
+
const gchar *CertUtil_GetToolDir(void);
+gboolean CheckRootPriv(void);
+
#endif // #ifndef _CERT_UTIL_H_
diff --git a/open-vm-tools/hgfsmounter/hgfsmounter.c b/open-vm-tools/hgfsmounter/hgfsmounter.c
index 875b403a..14a5c993 100644
--- a/open-vm-tools/hgfsmounter/hgfsmounter.c
+++ b/open-vm-tools/hgfsmounter/hgfsmounter.c
@@ -608,6 +608,67 @@ ParseTtl(const char *option, // IN: option string along with value
}
#endif
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ParseServerIno --
+ *
+ * A helper function to process a string containing serverino value.
+ *
+ * Results:
+ * TRUE always success.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+ParseServerIno(const char *option, // IN: option string along with value
+ HgfsMountInfo *mountInfo, // OUT: mount data
+ int *flags) // OUT: mount flags unused
+{
+ ASSERT(option);
+ ASSERT(mountInfo);
+
+ mountInfo->flags |= HGFS_MNTINFO_SERVER_INO;
+ LOG("Setting mount flag server ino in 0x%x\n", mountInfo->flags);
+ return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ParseNoServerIno --
+ *
+ * A helper function to process a string containing noserverino value.
+ *
+ * Results:
+ * TRUE always success.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+ParseNoServerIno(const char *option, // IN: option string along with value
+ HgfsMountInfo *mountInfo, // OUT: mount data
+ int *flags) // OUT: mount flags unused
+{
+ ASSERT(option);
+ ASSERT(mountInfo);
+
+ mountInfo->flags &= ~HGFS_MNTINFO_SERVER_INO;
+ LOG("Clearing mount flag server ino in 0x%x\n", mountInfo->flags);
+ return TRUE;
+}
+
+
static MountOptions mountOptions[] = {
{ "ro", MS_RDONLY, TRUE, "mount read-only",
"Setting mount read-only", NULL },
@@ -665,6 +726,12 @@ static MountOptions mountOptions[] = {
{ "bind", MS_MOVE, TRUE, "move an existig mount point",
"Setting mount type to move", NULL },
#endif
+ { "serverino", 0, TRUE,
+ "Use server generated inode numbers.\n",
+ "Setting mount option for using Server inode numbers on", ParseServerIno },
+ { "noserverino", 0, FALSE,
+ "Use client generated inode numbers.\n",
+ "Setting mount option for using Server inode numbers off", ParseNoServerIno },
{ "remount", MS_REMOUNT, TRUE, "remount already mounted filesystem",
"Setting mount type to remount", NULL }
@@ -1064,6 +1131,7 @@ main(int argc, // IN
}
mountInfo.magicNumber = HGFS_SUPER_MAGIC;
+ mountInfo.infoSize = sizeof mountInfo;
mountInfo.version = HGFS_PROTOCOL_VERSION;
#ifndef sun
@@ -1080,6 +1148,10 @@ main(int argc, // IN
mountInfo.shareNameDir = shareNameDir;
#endif
#endif
+ /*
+ * Default flags which maybe modified by user passed options.
+ */
+ mountInfo.flags = HGFS_MNTINFO_SERVER_INO;
/*
* This'll write the rest of the options into HgfsMountInfo and possibly
diff --git a/open-vm-tools/lib/Makefile.am b/open-vm-tools/lib/Makefile.am
index 8a904c8a..c980ba94 100644
--- a/open-vm-tools/lib/Makefile.am
+++ b/open-vm-tools/lib/Makefile.am
@@ -43,6 +43,9 @@ SUBDIRS += hgfsHelper
SUBDIRS += hgfsServer
SUBDIRS += hgfsServerManagerGuest
SUBDIRS += hgfsServerPolicyGuest
+if HAVE_GTKMM
+SUBDIRS += hgfsUri
+endif
SUBDIRS += impersonate
SUBDIRS += lock
SUBDIRS += message
@@ -51,7 +54,6 @@ SUBDIRS += netUtil
SUBDIRS += nicInfo
SUBDIRS += panic
SUBDIRS += panicDefault
-SUBDIRS += printer
SUBDIRS += procMgr
SUBDIRS += rpcChannel
SUBDIRS += rpcIn
diff --git a/open-vm-tools/lib/Makefile.in b/open-vm-tools/lib/Makefile.in
index 153f678f..e01e0619 100644
--- a/open-vm-tools/lib/Makefile.in
+++ b/open-vm-tools/lib/Makefile.in
@@ -50,7 +50,8 @@ build_triplet = @build@
host_triplet = @host@
@HAVE_X11_TRUE@am__append_1 = appUtil
@HAVE_VSOCK_TRUE@am__append_2 = asyncsocket
-@USE_SLASH_PROC_TRUE@am__append_3 = slashProc
+@HAVE_GTKMM_TRUE@am__append_3 = hgfsUri
+@USE_SLASH_PROC_TRUE@am__append_4 = slashProc
subdir = lib
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in COPYING
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -78,10 +79,11 @@ CTAGS = ctags
DIST_SUBDIRS = guestRpc appUtil auth backdoor asyncsocket sslDirect \
pollGtk poll dataMap hashMap dict dynxdr err file foundryMsg \
glibUtils guestApp hgfs hgfsBd hgfsHelper hgfsServer \
- hgfsServerManagerGuest hgfsServerPolicyGuest impersonate lock \
- message misc netUtil nicInfo panic panicDefault printer \
- procMgr rpcChannel rpcIn rpcOut rpcVmx slashProc string stubs \
- syncDriver system unicode user vmCheck vmSignal wiper xdg
+ hgfsServerManagerGuest hgfsServerPolicyGuest hgfsUri \
+ impersonate lock message misc netUtil nicInfo panic \
+ panicDefault procMgr rpcChannel rpcIn rpcOut rpcVmx slashProc \
+ string stubs syncDriver system unicode user vmCheck vmSignal \
+ wiper xdg
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@@ -275,9 +277,9 @@ SUBDIRS = guestRpc $(am__append_1) auth backdoor $(am__append_2) \
sslDirect pollGtk poll dataMap hashMap dict dynxdr err file \
foundryMsg glibUtils guestApp hgfs hgfsBd hgfsHelper \
hgfsServer hgfsServerManagerGuest hgfsServerPolicyGuest \
- impersonate lock message misc netUtil nicInfo panic \
- panicDefault printer procMgr rpcChannel rpcIn rpcOut rpcVmx \
- $(am__append_3) string stubs syncDriver system unicode user \
+ $(am__append_3) impersonate lock message misc netUtil nicInfo \
+ panic panicDefault procMgr rpcChannel rpcIn rpcOut rpcVmx \
+ $(am__append_4) string stubs syncDriver system unicode user \
vmCheck vmSignal wiper xdg
all: all-recursive
diff --git a/open-vm-tools/lib/appUtil/appUtil.c b/open-vm-tools/lib/appUtil/appUtil.c
index 54bd9a28..ae5acdca 100644
--- a/open-vm-tools/lib/appUtil/appUtil.c
+++ b/open-vm-tools/lib/appUtil/appUtil.c
@@ -22,6 +22,8 @@
* Utility functions for guest applications.
*/
+#include "appUtil.h"
+
#include <stdlib.h>
#include <string.h>
@@ -38,7 +40,7 @@
* AppUtil_SendGuestCaps --
*
* Send a list of guest capabilities to the host.
- *
+ *
* Results:
* None.
*
diff --git a/open-vm-tools/lib/appUtil/appUtilX11.c b/open-vm-tools/lib/appUtil/appUtilX11.c
index 1ce44a77..8d1dfb5b 100644
--- a/open-vm-tools/lib/appUtil/appUtilX11.c
+++ b/open-vm-tools/lib/appUtil/appUtilX11.c
@@ -101,7 +101,7 @@ static void
AppUtilCollectNamedIcons(GPtrArray *pixbufs, // IN/OUT
const char *iconName) // IN
{
- char *myIconName;
+ char *myIconName = NULL;
char *baseIconName;
/*
* Use the GtkIconTheme to track down any available icons for this app.
diff --git a/open-vm-tools/lib/asyncsocket/asyncSocketInt.h b/open-vm-tools/lib/asyncsocket/asyncSocketInt.h
index 6ee8244c..322f0238 100644
--- a/open-vm-tools/lib/asyncsocket/asyncSocketInt.h
+++ b/open-vm-tools/lib/asyncsocket/asyncSocketInt.h
@@ -108,18 +108,10 @@
#define ASOCK_EWOULDBLOCK EWOULDBLOCK
#endif
-
-typedef struct WebSocketHandshakeState {
- char *handshakeBuffer;
- int32 numValidBytes; // The number of bytes in the buffer that constitute the header
- int32 httpHeaderLength;
-} WebSocketHandshakeState;
-
typedef enum {
- WEB_SOCKET_FRAME_TYPE_UNKNOWN = 0,
- WEB_SOCKET_FRAME_TYPE_RAW = 1,
- WEB_SOCKET_FRAME_TYPE_UTF8 = 2,
-} WebSocketFrameType;
+ WEB_SOCKET_FRAME_OPCODE_BINARY = 0x02,
+ WEB_SOCKET_FRAME_OPCODE_CLOSE = 0x08,
+} WebSocketFrameOpcode;
typedef enum {
WEB_SOCKET_STATE_CONNECTING = 0,
@@ -129,12 +121,12 @@ typedef enum {
} WebSocketState;
typedef enum {
- WEB_SOCKET_HYBI_NEED_FRAME_TYPE = 0,
- WEB_SOCKET_HYBI_NEED_FRAME_SIZE = 1,
- WEB_SOCKET_HYBI_NEED_EXTENDED_FRAME_SIZE = 2,
- WEB_SOCKET_HYBI_NEED_FRAME_MASK = 3,
- WEB_SOCKET_HYBI_NEED_FRAME_DATA = 4,
-} WebSocketHybiDecodeState;
+ WEB_SOCKET_NEED_FRAME_TYPE = 0,
+ WEB_SOCKET_NEED_FRAME_SIZE = 1,
+ WEB_SOCKET_NEED_EXTENDED_FRAME_SIZE = 2,
+ WEB_SOCKET_NEED_FRAME_MASK = 3,
+ WEB_SOCKET_NEED_FRAME_DATA = 4,
+} WebSocketDecodeState;
/*
* Bitmask indicates when masking should be applyed or removed,
@@ -145,10 +137,10 @@ typedef enum {
* server.
*/
typedef enum {
- WEB_SOCKET_HYBI_MASKING_NONE = 0,
- WEB_SOCKET_HYBI_MASKING_RECV = 1,
- WEB_SOCKET_HYBI_MASKING_SEND = 1 << 1,
-} WebSocketHybiMaskingRequired;
+ WEB_SOCKET_MASKING_NONE = 0,
+ WEB_SOCKET_MASKING_RECV = 1,
+ WEB_SOCKET_MASKING_SEND = 1 << 1,
+} WebSocketMaskingRequired;
typedef enum {
ASYNCSOCKET_TYPE_SOCKET = 0,
@@ -164,7 +156,13 @@ typedef struct SendBufList {
int len;
AsyncSocketSendFn sendFn;
void *clientData;
- char *base64Buf;
+ /*
+ * If the data needs to be encoded somehow before sending over the
+ * wire, this will point to an internally-allocated buffer
+ * containing the encoded version of buf. The len field above will
+ * hold the length of the encoded data.
+ */
+ char *encodedBuf;
} SendBufList;
struct AsyncSocket {
@@ -196,6 +194,7 @@ struct AsyncSocket {
int recvPos;
int recvLen;
Bool recvCb;
+ Bool recvCbTimer;
Bool recvFireOnPartial;
SendBufList *sendBufList;
@@ -203,11 +202,13 @@ struct AsyncSocket {
int sendPos;
Bool sendCb;
Bool sendCbTimer;
+ Bool sendCbRT;
Bool sendBufFull;
Bool sendLowLatency;
Bool sslConnected;
+ uint8 inIPollCb;
Bool inRecvLoop;
uint32 inBlockingRecv;
@@ -223,34 +224,35 @@ struct AsyncSocket {
char *origin;
char *host;
char *hostname;
- char *protocol;
char *uri;
char *cookie;
int version;
- WebSocketHybiMaskingRequired maskingRequirements;
- WebSocketFrameType currentFrameType;
+ WebSocketMaskingRequired maskingRequirements;
+ WebSocketFrameOpcode frameOpcode;
WebSocketState state;
void *connectClientData;
// Saved error reporting values.
AsyncSocketErrorFn errorFn;
void *errorClientData;
char *socketBuffer; // Accumulates incoming data (including framing etc.)
- char *decodeBuffer; // Accumulates incoming data after removing framing and base64 decoding
- int32 socketBufferWriteOffset; // Offset into socket buffer for raw incoming data.
- int32 socketBufferBase64DecodeReadOffset; // Offset into socket buffer for data waiting to be base64 decoded
- int32 decodeBufferBase64DecodeWriteOffset; // Offset into decode buffer for base64 decoded data
- int32 decodeBufferReadOffset; // Offset into decode buffer for data to be consumed by our caller
- size_t hybiFrameBytesRemaining;
- Bool hybiMaskPresent;
- uint8 hybiMaskBytes[4];
- uint8 hybiMaskOffset;
- int streamProtocol;
- size_t hybiCurrentFrameSize;
- WebSocketHybiDecodeState hybiCurrentDecodeState;
+ char *decodeBuffer; // Accumulates incoming data after removing framing
+ int32 socketBufferWriteOffset;
+ int32 socketBufferReadOffset;
+ int32 decodeBufferWriteOffset;
+ int32 decodeBufferReadOffset;
+ size_t frameBytesRemaining;
+ size_t frameSize;
+ Bool maskPresent;
+ uint8 maskBytes[4];
+ uint8 maskOffset;
+ const char **streamProtocols; // null terminated list of protocols
+ const char *streamProtocol; // points to one of the above.
+ WebSocketDecodeState decodeState;
Bool useSSL;
- Bool permitUnverifiedSSL;
+ SSLVerifyParam *sslVerifyParam; // Used for certificate verifications
char *upgradeNonceBase64;
rqContext *randomContext;
+ uint16 closeStatus;
} webSocket;
#ifdef _WIN32
@@ -340,7 +342,8 @@ void AsyncSocketCloseSocket(AsyncSocket *asock);
#ifndef VMX86_TOOLS
void AsyncSocketInitWebSocket(AsyncSocket *asock,
void *clientData,
- Bool useSSL);
+ Bool useSSL,
+ const char *protocols[]);
#endif
AsyncSocket *AsyncSocketListenImpl(struct sockaddr_storage *addr,
socklen_t addrLen,
@@ -349,6 +352,7 @@ AsyncSocket *AsyncSocketListenImpl(struct sockaddr_storage *addr,
AsyncSocketPollParams *pollParams,
Bool isWebSock,
Bool webSockUseSSL,
+ const char *protocols[],
int *outError);
AsyncSocket *AsyncSocketListenerCreate(const char *addrStr,
unsigned int port,
@@ -357,6 +361,7 @@ AsyncSocket *AsyncSocketListenerCreate(const char *addrStr,
AsyncSocketPollParams *pollParams,
Bool isWebSock,
Bool webSockUseSSL,
+ const char *protocols[],
int *outError);
#endif // __ASYNC_SOCKET_INT_H__
diff --git a/open-vm-tools/lib/asyncsocket/asyncsocket.c b/open-vm-tools/lib/asyncsocket/asyncsocket.c
index 3afcbdea..05f217a2 100644
--- a/open-vm-tools/lib/asyncsocket/asyncsocket.c
+++ b/open-vm-tools/lib/asyncsocket/asyncsocket.c
@@ -96,6 +96,9 @@
#define PORT_STRING_LEN 6 /* "12345\0" or ":12345" */
+#define IN_IPOLL_RECV (1 << 0)
+#define IN_IPOLL_SEND (1 << 1)
+
/*
* INET6_ADDRSTRLEN allows for only 45 characters. If we somehow have a
* non-recommended V4MAPPED address we can exceed 45 total characters in our
@@ -357,6 +360,9 @@ AsyncSocket_MsgError(int asyncSockError) // IN
case ASOCKERR_LISTEN:
result = MSGID(asyncsocket.listen) "Socket listen error";
break;
+ case ASOCKERR_CONNECTSSL:
+ result = MSGID(asyncsocket.connectssl) "Connection error: could not negotiate SSL";
+ break;
}
if (!result) {
@@ -669,6 +675,7 @@ AsyncSocketListenImpl(struct sockaddr_storage *addr, // IN
AsyncSocketPollParams *pollParams, // IN: optional
Bool isWebSock, // IN
Bool webSockUseSSL, // IN:
+ const char *protocols[], // IN: optional
int *outError) // OUT: optional
{
AsyncSocket *asock = AsyncSocketInit(addr->ss_family, pollParams, outError);
@@ -676,7 +683,7 @@ AsyncSocketListenImpl(struct sockaddr_storage *addr, // IN
if (asock != NULL) {
#ifndef VMX86_TOOLS
if (isWebSock) {
- AsyncSocketInitWebSocket(asock, clientData, webSockUseSSL);
+ AsyncSocketInitWebSocket(asock, clientData, webSockUseSSL, protocols);
}
#endif
@@ -717,6 +724,7 @@ AsyncSocketListenerCreateImpl(const char *addrStr, // IN: optiona
AsyncSocketPollParams *pollParams, // IN
Bool isWebSock, // IN
Bool webSockUseSSL, // IN
+ const char *protocols[], // IN: optional
int *outError) // OUT: optional
{
AsyncSocket *asock = NULL;
@@ -730,7 +738,7 @@ AsyncSocketListenerCreateImpl(const char *addrStr, // IN: optiona
if (getaddrinfoError == 0) {
asock = AsyncSocketListenImpl(&addr, addrLen, connectFn, clientData,
pollParams, isWebSock, webSockUseSSL,
- outError);
+ protocols, outError);
if (asock) {
ASOCKLG0(asock,
@@ -800,13 +808,14 @@ AsyncSocketListenerCreate(const char *addrStr, // IN: optional
AsyncSocketPollParams *pollParams, // IN
Bool isWebSock, // IN
Bool webSockUseSSL, // IN
+ const char *protocols[], // IN: optional
int *outError) // OUT: optional
{
if (addrStr != NULL && *addrStr != '\0' &&
Str_Strcmp(addrStr, "localhost")) {
return AsyncSocketListenerCreateImpl(addrStr, port, AF_UNSPEC, connectFn,
clientData, pollParams, FALSE,
- FALSE, outError);
+ FALSE, protocols, outError);
} else {
Bool localhost = addrStr != NULL && !Str_Strcmp(addrStr, "localhost");
unsigned int tempPort = port;
@@ -817,7 +826,7 @@ AsyncSocketListenerCreate(const char *addrStr, // IN: optional
asock6 = AsyncSocketListenerCreateImpl(addrStr, port, AF_INET6,
connectFn, clientData, pollParams,
- isWebSock, webSockUseSSL,
+ isWebSock, webSockUseSSL, protocols,
&tempError6);
if (localhost && port == 0) {
@@ -832,7 +841,7 @@ AsyncSocketListenerCreate(const char *addrStr, // IN: optional
asock4 = AsyncSocketListenerCreateImpl(addrStr, tempPort, AF_INET,
connectFn, clientData, pollParams,
isWebSock, webSockUseSSL,
- &tempError4);
+ protocols, &tempError4);
if (localhost && port == 0 && tempError4 == ASOCKERR_BINDADDRINUSE) {
Log(ASOCKPREFIX "Failed to reuse IPv6 localhost port number for IPv4 "
@@ -843,7 +852,8 @@ AsyncSocketListenerCreate(const char *addrStr, // IN: optional
asock4 = AsyncSocketListenerCreateImpl(addrStr, port, AF_INET,
connectFn, clientData,
pollParams, isWebSock,
- webSockUseSSL, &tempError4);
+ webSockUseSSL, protocols,
+ &tempError4);
tempPort = AsyncSocket_GetPort(asock4);
if (tempPort == MAX_UINT32) {
@@ -856,7 +866,8 @@ AsyncSocketListenerCreate(const char *addrStr, // IN: optional
asock6 = AsyncSocketListenerCreateImpl(addrStr, tempPort, AF_INET6,
connectFn, clientData,
pollParams, isWebSock,
- webSockUseSSL, &tempError6);
+ webSockUseSSL, protocols,
+ &tempError6);
if (!asock6 && tempError6 == ASOCKERR_BINDADDRINUSE) {
Log(ASOCKPREFIX "Failed to reuse IPv4 localhost port number for "
@@ -937,12 +948,12 @@ AsyncSocketListenerCreateLoopback(unsigned int port, // IN
asock6 = AsyncSocketListenerCreateImpl("::1", port, AF_INET6,
connectFn, clientData, pollParams,
isWebSock, webSockUseSSL,
- &tempError6);
+ NULL, &tempError6);
asock4 = AsyncSocketListenerCreateImpl("127.0.0.1", port, AF_INET,
connectFn, clientData, pollParams,
isWebSock, webSockUseSSL,
- &tempError4);
+ NULL, &tempError4);
if (asock6 && asock4) {
AsyncSocket *asock;
@@ -1022,7 +1033,7 @@ AsyncSocket_Listen(const char *addrStr, // IN: optional
int *outError) // OUT: optional
{
return AsyncSocketListenerCreate(addrStr, port, connectFn, clientData,
- pollParams, FALSE, FALSE, outError);
+ pollParams, FALSE, FALSE, NULL, outError);
}
@@ -1035,9 +1046,6 @@ AsyncSocket_Listen(const char *addrStr, // IN: optional
* families and accepts new connections. Fires the connect callback with
* new AsyncSocket object for each connection.
*
- * If port requested is 0, we will let the system assign the first
- * available port.
- *
* Results:
* New AsyncSocket in listening state or NULL on error.
*
@@ -1095,7 +1103,7 @@ AsyncSocket_ListenVMCI(unsigned int cid, // IN
asock = AsyncSocketListenImpl((struct sockaddr_storage *)&addr, sizeof addr,
connectFn, clientData, pollParams, FALSE,
- FALSE, outError);
+ FALSE, NULL, outError);
VMCISock_ReleaseAFValueFd(vsockDev);
return asock;
@@ -1274,7 +1282,15 @@ AsyncSocketOSVersionSupportsV4Mapped()
{
#ifdef _WIN32
OSVERSIONINFOW osvi = {sizeof(OSVERSIONINFOW)};
+
+ /*
+ * Starting with msvc-12.0 / SDK v8.1 GetVersionEx is deprecated.
+ * Bug 1259185 tracks switching to VerifyVersionInfo.
+ */
+
+#pragma warning(suppress : 4996) // 'function': was declared deprecated
GetVersionExW(&osvi);
+
/* Windows version is at least Vista or higher */
return osvi.dwMajorVersion >= 6;
#else
@@ -2162,14 +2178,14 @@ AsyncSocketRecvSocket(AsyncSocket *asock, // IN:
{
int retVal = ASOCKERR_SUCCESS;
- if (!asock->recvBuf && !asock->recvCb) {
+ if (!asock->recvCb) {
VMwareStatus pollStatus;
/*
* Register the Poll callback
*/
- ASOCKLOG(3, asock, ("installing recv poll callback\n"));
+ ASOCKLOG(3, asock, ("installing recv periodic poll callback\n"));
pollStatus = AsyncSocketPollAdd(asock, TRUE,
POLL_FLAG_READ | POLL_FLAG_PERIODIC,
@@ -2185,12 +2201,12 @@ AsyncSocketRecvSocket(AsyncSocket *asock, // IN:
if (AsyncSocketHasDataPending(asock) && !asock->inRecvLoop) {
ASOCKLOG(0, asock, ("installing recv RTime poll callback\n"));
- if (Poll_CB_RTime(asock->vt->recvCallback,
- asock, 0, FALSE, NULL) !=
+ if (AsyncSocketPollAdd(asock, FALSE, 0, asock->vt->recvCallback, 0) !=
VMWARE_STATUS_SUCCESS) {
retVal = ASOCKERR_POLL;
goto out;
}
+ asock->recvCbTimer = TRUE;
}
out:
@@ -2476,6 +2492,7 @@ AsyncSocketPoll(AsyncSocket *s, // IN:
if (read && s->fd == -1) {
if (!s->listenAsock4 && !s->listenAsock6) {
ASSERT(FALSE);
+ ASOCKLG0(s, ("%s: Failed to find listener socket.\n", __FUNCTION__));
return ASOCKERR_GENERIC;
}
@@ -2587,26 +2604,37 @@ AsyncSocketPoll(AsyncSocket *s, // IN:
}
#endif
- ASOCKWARN(s, ("Failed to return a ready socket.\n"));
+ ASOCKWARN(s, ("%s: Failed to return a ready socket.\n",
+ __FUNCTION__));
return ASOCKERR_GENERIC;
}
case 0:
/*
* No sockets were ready within the specified time.
*/
+ ASOCKLG0(s, ("%s: Timeout waiting for a ready socket.\n",
+ __FUNCTION__));
return ASOCKERR_TIMEOUT;
- case -1:
- if (ASOCK_LASTERROR() == EINTR) {
+ case -1: {
+ int sysErr = ASOCK_LASTERROR();
+
+ if (sysErr == EINTR) {
/*
* We were somehow interrupted by signal. Let's loop and retry.
*/
+ ASOCKLG0(s, ("%s: Socket interrupted by a signal.\n",
+ __FUNCTION__));
continue;
}
- s->genericErrno = ASOCK_LASTERROR();
+ s->genericErrno = sysErr;
+
+ ASOCKLG0(s, ("%s: Failed with error %d: %s\n", __FUNCTION__, sysErr,
+ Err_Errno2String(sysErr)));
return ASOCKERR_GENERIC;
+ }
default:
NOT_REACHED();
}
@@ -2798,7 +2826,8 @@ AsyncSocketSendSocket(AsyncSocket *asock, // IN:
* already make 0-byte send() to force WSAEWOULDBLOCK.
*/
- if (AsyncSocketPollAdd(asock, FALSE, 0, asock->vt->sendCallback, 0)
+ if (AsyncSocketPollAdd(asock, FALSE, 0, asock->vt->sendCallback,
+ asock->pollParams.iPoll != NULL ? 1 : 0)
!= VMWARE_STATUS_SUCCESS) {
retVal = ASOCKERR_POLL;
return retVal;
@@ -2992,8 +3021,8 @@ AsyncSocketResolveAddr(const char *hostname,
#if defined(_WIN32)
DWORD len = ARRAYSIZE(tempAddrString);
- if (WSAAddressToString(aiIterator->ai_addr, aiIterator->ai_addrlen,
- NULL, tempAddrString, &len)) {
+ if (WSAAddressToStringA(aiIterator->ai_addr, aiIterator->ai_addrlen,
+ NULL, tempAddrString, &len)) {
*addrString = Util_SafeStrdup(unknownAddr);
} else {
*addrString = Util_SafeStrdup(tempAddrString);
@@ -3279,7 +3308,7 @@ AsyncSocketDispatchSentBuffer(AsyncSocket *s)
s->sendBufTail = &(s->sendBufList);
}
s->sendPos = 0;
- free(tmp.base64Buf);
+ free(tmp.encodedBuf);
free(head);
if (tmp.sendFn) {
@@ -3343,9 +3372,9 @@ AsyncSocketWriteBuffers(AsyncSocket *s)
int left = head->len - s->sendPos;
int sizeToSend = head->len;
- if (head->base64Buf) {
+ if (head->encodedBuf) {
sent = SSL_Write(s->sslSock,
- (uint8 *) head->base64Buf + s->sendPos, left);
+ (uint8 *) head->encodedBuf + s->sendPos, left);
} else {
sent = SSL_Write(s->sslSock,
(uint8 *) head->buf + s->sendPos, left);
@@ -3784,16 +3813,12 @@ AsyncSocket_DoOneMsg(AsyncSocket *s, Bool read, int timeoutMS)
* after reading the data.
*/
- Bool removed;
-
AsyncSocketLock(s);
ASSERT(s->state == AsyncSocketConnected);
ASSERT(s->recvCb); /* We are supposed to call someone... */
AsyncSocketAddRef(s);
- removed = AsyncSocketPollRemove(s, TRUE,
- POLL_FLAG_READ | POLL_FLAG_PERIODIC,
- s->vt->recvCallback);
- ASSERT(removed || s->pollParams.iPoll);
+ s->vt->cancelRecvCb(s);
+ s->recvCb = TRUE; /* We need to know if the callback cancel recv. */
s->inBlockingRecv++;
AsyncSocketUnlock(s); /* We may sleep in poll. */
@@ -3816,22 +3841,20 @@ AsyncSocket_DoOneMsg(AsyncSocket *s, Bool read, int timeoutMS)
* it above.
*/
- if (s->state != AsyncSocketClosed) {
- VMwareStatus pollStatus;
-
- ASSERT(s->refCount > 1); /* We should not be last user of socket */
+ if (s->state != AsyncSocketClosed && s->recvCb) {
+ ASSERT(s->refCount > 1); /* We should not be last user of socket. */
ASSERT(s->state == AsyncSocketConnected);
- ASSERT(s->recvCb); /* Still interested in callback. */
- pollStatus = AsyncSocketPollAdd(s, TRUE,
- POLL_FLAG_READ | POLL_FLAG_PERIODIC,
- s->vt->recvCallback);
-
- if (pollStatus != VMWARE_STATUS_SUCCESS) {
- ASOCKWARN(s, ("failed to install recv callback!\n"));
- AsyncSocketRelease(s, TRUE);
-
- retVal = ASOCKERR_POLL;
- goto out;
+ /*
+ * If AsyncSocketPoll or AsyncSocketFillRecvBuffer fails, do not
+ * add the recv callback as it may never fire.
+ */
+ s->recvCb = FALSE; /* For re-registering the poll callback. */
+ if (retVal == ASOCKERR_SUCCESS || retVal == ASOCKERR_TIMEOUT) {
+ retVal = s->vt->recv(s, (uint8 *)s->recvBuf + s->recvPos,
+ s->recvLen - s->recvPos);
+ }
+ if (retVal != ASOCKERR_SUCCESS) {
+ s->recvBuf = NULL;
}
}
/* This may destroy socket s if it is in AsyncSocketClosed state now. */
@@ -3851,7 +3874,6 @@ AsyncSocket_DoOneMsg(AsyncSocket *s, Bool read, int timeoutMS)
}
}
-out:
return retVal;
}
@@ -4066,6 +4088,10 @@ AsyncSocketCancelRecvCbSocket(AsyncSocket *asock) // IN:
{
ASSERT(AsyncSocketIsLocked(asock));
+ if (asock->recvCbTimer) {
+ AsyncSocketPollRemove(asock, FALSE, 0, asock->vt->recvCallback);
+ asock->recvCbTimer = FALSE;
+ }
if (asock->recvCb) {
Bool removed;
ASOCKLOG(1, asock, ("Removing poll recv callback while cancelling recv.\n"));
@@ -4126,24 +4152,18 @@ AsyncSocketCancelCbForCloseSocket(AsyncSocket *asock) // IN:
ASSERT(!asock->recvBuf || asock->recvCb);
+ if (asock->recvCbTimer) {
+ AsyncSocketPollRemove(asock, FALSE, 0, asock->vt->recvCallback);
+ asock->recvCbTimer = FALSE;
+ }
if (asock->recvCb) {
ASOCKLOG(1, asock, ("recvCb is non-NULL, removing recv callback\n"));
removed = AsyncSocketPollRemove(asock, TRUE,
POLL_FLAG_READ | POLL_FLAG_PERIODIC,
asock->vt->recvCallback);
-
- /*
- * Callback might be temporarily removed in AsyncSocket_DoOneMsg.
- */
-
+ /* Callback might be temporarily removed in AsyncSocket_DoOneMsg. */
ASSERT_NOT_TESTED(removed || asock->pollParams.iPoll);
- /*
- * We may still have the RTime callback, try to remove if it exists
- */
-
- removed = Poll_CB_RTimeRemove(asock->vt->recvCallback,
- asock, FALSE);
asock->recvCb = FALSE;
asock->recvBuf = NULL;
}
@@ -4220,9 +4240,9 @@ AsyncSocketCancelCbForCloseInt(AsyncSocket *asock) // IN:
int pos = asock->sendPos;
/*
- * Free the Base64 encoded data if it exists.
+ * Free the encoded data if it exists.
*/
- free(cur->base64Buf);
+ free(cur->encodedBuf);
asock->sendBufList = asock->sendBufList->next;
asock->sendPos = 0;
@@ -4529,7 +4549,7 @@ AsyncSocketSendInternal(AsyncSocket *asock, // IN
* Allocate and initialize new send buffer entry
*/
- newBuf = Util_SafeCalloc(1, sizeof(SendBufList));
+ newBuf = Util_SafeCalloc(1, sizeof *newBuf);
newBuf->buf = buf;
newBuf->len = len;
newBuf->sendFn = sendFn;
@@ -4727,7 +4747,7 @@ AsyncSocketHandleError(AsyncSocket *asock, int asockErr)
static void
AsyncSocketAcceptCallback(void *clientData)
{
- AsyncSocket *asock = (AsyncSocket *) clientData;
+ AsyncSocket *asock = clientData;
int retval;
ASSERT(asock);
@@ -4769,7 +4789,7 @@ AsyncSocketAcceptCallback(void *clientData)
static void
AsyncSocketConnectCallback(void *clientData)
{
- AsyncSocket *asock = (AsyncSocket *) clientData;
+ AsyncSocket *asock = clientData;
int retval;
ASSERT(asock);
@@ -4807,7 +4827,7 @@ AsyncSocketConnectCallback(void *clientData)
void
AsyncSocketRecvCallback(void *clientData)
{
- AsyncSocket *asock = (AsyncSocket *) clientData;
+ AsyncSocket *asock = clientData;
int error;
ASSERT(asock);
@@ -4850,7 +4870,7 @@ AsyncSocketIPollRecvCallback(void *clientData) // IN:
#ifdef VMX86_TOOLS
NOT_IMPLEMENTED();
#else
- AsyncSocket *asock = (AsyncSocket *) clientData;
+ AsyncSocket *asock = clientData;
MXUserRecLock *lock;
ASSERT(asock);
@@ -4859,8 +4879,14 @@ AsyncSocketIPollRecvCallback(void *clientData) // IN:
!MXUser_IsCurThreadHoldingRecLock(asock->pollParams.lock));
AsyncSocketLock(asock);
+ if (asock->recvCbTimer) {
+ /* IVmdbPoll only has periodic callbacks. */
+ AsyncSocketIPollRemove(asock, FALSE, 0, asock->vt->recvCallback);
+ asock->recvCbTimer = FALSE;
+ }
+ asock->inIPollCb |= IN_IPOLL_RECV;
lock = asock->pollParams.lock;
- if (asock->recvCb) {
+ if (asock->recvCb && asock->inBlockingRecv == 0) {
/*
* There is no need to take a reference here -- the fact that this
* callback is running means AsyncsocketIPollRemove would not release a
@@ -4873,6 +4899,7 @@ AsyncSocketIPollRecvCallback(void *clientData) // IN:
}
}
+ asock->inIPollCb &= ~IN_IPOLL_RECV;
if (asock->recvCb) {
AsyncSocketUnlock(asock);
} else {
@@ -4911,7 +4938,7 @@ AsyncSocketIPollRecvCallback(void *clientData) // IN:
void
AsyncSocketSendCallback(void *clientData)
{
- AsyncSocket *s = (AsyncSocket *) clientData;
+ AsyncSocket *s = clientData;
int retval;
ASSERT(s);
@@ -4983,13 +5010,14 @@ AsyncSocketIPollSendCallback(void *clientData) // IN:
#ifdef VMX86_TOOLS
NOT_IMPLEMENTED();
#else
- AsyncSocket *s = (AsyncSocket *) clientData;
+ AsyncSocket *s = clientData;
MXUserRecLock *lock;
ASSERT(s);
ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
AsyncSocketLock(s);
+ s->inIPollCb |= IN_IPOLL_SEND;
lock = s->pollParams.lock;
if (s->sendCb) {
/*
@@ -5008,6 +5036,7 @@ AsyncSocketIPollSendCallback(void *clientData) // IN:
AsyncSocketSendCallback(s);
}
+ s->inIPollCb &= ~IN_IPOLL_SEND;
AsyncSocketRelease(s, TRUE);
if (lock != NULL) {
MXUser_DecRefRecLock(lock);
@@ -5296,10 +5325,18 @@ AsyncSocketIPollRemove(AsyncSocket *asock,
ret = poll->UnregisterTimer(poll, callback, asock);
}
- if (ret) {
+ if (ret &&
+ !((asock->inIPollCb & IN_IPOLL_RECV) != 0 &&
+ callback == asock->vt->recvCallback) &&
+ !((asock->inIPollCb & IN_IPOLL_SEND) != 0 &&
+ callback == asock->vt->sendCallback)) {
MXUserRecLock *lock = asock->pollParams.lock;
- /* Release the reference taken when registering the callback. */
+ /*
+ * As the callback has been unregistered and we are not currently in
+ * the callback being removed, we can safely release the reference taken
+ * when registering the callback.
+ */
AsyncSocketRelease(asock, FALSE);
if (lock != NULL) {
MXUser_DecRefRecLock(lock);
@@ -5311,8 +5348,6 @@ AsyncSocketIPollRemove(AsyncSocket *asock,
}
-
-
/*
*-----------------------------------------------------------------------------
*
@@ -5484,12 +5519,18 @@ AsyncSocket_GetReceivedFd(AsyncSocket *asock) // IN
Bool
AsyncSocket_ConnectSSL(AsyncSocket *asock, // IN
- SSLVerifyParam *verifyParam) // IN/OPT
+ SSLVerifyParam *verifyParam, // IN/OPT
+ void *sslContext) // IN/OPT
{
ASSERT(asock);
ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
- return SSL_ConnectAndVerify(asock->sslSock, verifyParam);
+ if (sslContext == NULL) {
+ sslContext = SSL_DefaultContext();
+ }
+
+ return SSL_ConnectAndVerifyWithContext(asock->sslSock, verifyParam,
+ sslContext);
}
@@ -5540,7 +5581,7 @@ static void
AsyncSocketSslAcceptCallback(void *clientData)
{
int sslOpCode;
- AsyncSocket *asock = (AsyncSocket *) clientData;
+ AsyncSocket *asock = clientData;
VMwareStatus pollStatus;
ASSERT(asock);
diff --git a/open-vm-tools/lib/auth/authPosix.c b/open-vm-tools/lib/auth/authPosix.c
index 6464e96a..e75da98d 100644
--- a/open-vm-tools/lib/auth/authPosix.c
+++ b/open-vm-tools/lib/auth/authPosix.c
@@ -202,12 +202,12 @@ static int PAM_conv (int num_msg, // IN:
#endif
{
int count;
- struct pam_response *reply = calloc(num_msg, sizeof(struct pam_response));
+ struct pam_response *reply = calloc(num_msg, sizeof *reply);
if (!reply) {
return PAM_CONV_ERR;
}
-
+
for (count = 0; count < num_msg; count++) {
switch (msg[count]->msg_style) {
case PAM_PROMPT_ECHO_ON:
@@ -238,7 +238,7 @@ static int PAM_conv (int num_msg, // IN:
return PAM_CONV_ERR;
}
}
-
+
*resp = reply;
return PAM_SUCCESS;
@@ -376,7 +376,7 @@ Auth_AuthenticateSelf(void) // IN
* None.
*
* Results:
- *
+ *
* The vmauthToken for the authenticated user, or NULL if
* authentication failed.
*
diff --git a/open-vm-tools/lib/backdoor/backdoor.c b/open-vm-tools/lib/backdoor/backdoor.c
index 2e10fdef..13065dfb 100644
--- a/open-vm-tools/lib/backdoor/backdoor.c
+++ b/open-vm-tools/lib/backdoor/backdoor.c
@@ -49,6 +49,15 @@ extern "C" {
#include "backdoor.h"
#include "backdoorInt.h"
+#ifdef USE_VALGRIND
+/*
+ * When running under valgrind, we need to ensure we have the correct register
+ * state when poking the backdoor. The VALGRIND_NON_SIMD_CALLx macros are used
+ * to escape from the valgrind emulated CPU to the physical CPU.
+ */
+#include "vm_valgrind.h"
+#endif
+
#if defined(BACKDOOR_DEBUG) && defined(USERLEVEL)
#if defined(__KERNEL__) || defined(_KERNEL)
#else
@@ -180,6 +189,14 @@ BackdoorPrintHbProtoStruct(Backdoor_proto_hb *myBp)
*-----------------------------------------------------------------------------
*/
+#ifdef USE_VALGRIND
+static void
+Backdoor_InOutValgrind(uint16 tid, Backdoor_proto *myBp)
+{
+ Backdoor_InOut(myBp);
+}
+#endif
+
void
Backdoor(Backdoor_proto *myBp) // IN/OUT
{
@@ -191,7 +208,11 @@ Backdoor(Backdoor_proto *myBp) // IN/OUT
BACKDOOR_LOG(("Backdoor: before "));
BACKDOOR_LOG_PROTO_STRUCT(myBp);
+#ifdef USE_VALGRIND
+ VALGRIND_NON_SIMD_CALL1(Backdoor_InOutValgrind, myBp);
+#else
Backdoor_InOut(myBp);
+#endif
BACKDOOR_LOG(("Backdoor: after "));
BACKDOOR_LOG_PROTO_STRUCT(myBp);
@@ -215,6 +236,14 @@ Backdoor(Backdoor_proto *myBp) // IN/OUT
*-----------------------------------------------------------------------------
*/
+#ifdef USE_VALGRIND
+static void
+BackdoorHbOutValgrind(uint16 tid, Backdoor_proto_hb *myBp)
+{
+ BackdoorHbOut(myBp);
+}
+#endif
+
void
Backdoor_HbOut(Backdoor_proto_hb *myBp) // IN/OUT
{
@@ -226,7 +255,11 @@ Backdoor_HbOut(Backdoor_proto_hb *myBp) // IN/OUT
BACKDOOR_LOG(("Backdoor_HbOut: before "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
+#ifdef USE_VALGRIND
+ VALGRIND_NON_SIMD_CALL1(BackdoorHbOutValgrind, myBp);
+#else
BackdoorHbOut(myBp);
+#endif
BACKDOOR_LOG(("Backdoor_HbOut: after "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
@@ -250,6 +283,14 @@ Backdoor_HbOut(Backdoor_proto_hb *myBp) // IN/OUT
*-----------------------------------------------------------------------------
*/
+#ifdef USE_VALGRIND
+static void
+BackdoorHbInValgrind(uint16 tid, Backdoor_proto_hb *myBp)
+{
+ BackdoorHbIn(myBp);
+}
+#endif
+
void
Backdoor_HbIn(Backdoor_proto_hb *myBp) // IN/OUT
{
@@ -261,7 +302,11 @@ Backdoor_HbIn(Backdoor_proto_hb *myBp) // IN/OUT
BACKDOOR_LOG(("Backdoor_HbIn: before "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
+#ifdef USE_VALGRIND
+ VALGRIND_NON_SIMD_CALL1(BackdoorHbInValgrind, myBp);
+#else
BackdoorHbIn(myBp);
+#endif
BACKDOOR_LOG(("Backdoor_HbIn: after "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
diff --git a/open-vm-tools/lib/dict/dictll.c b/open-vm-tools/lib/dict/dictll.c
index d3cdb871..ebe06395 100644
--- a/open-vm-tools/lib/dict/dictll.c
+++ b/open-vm-tools/lib/dict/dictll.c
@@ -243,7 +243,7 @@ DictLL_UnmarshalLine(const char *buf, // IN: buffer to parse
*value = NULL;
return NULL;
}
-
+
/* Find end of this line, beginning of next. */
lineEnd = memchr(buf, '\n', bufSize);
if (lineEnd != NULL) {
@@ -339,18 +339,18 @@ DictLL_ReadLine(FILE *stream, // IN: stream to read
ASSERT(line);
ASSERT(name);
ASSERT(value);
-
+
*line = NULL;
*name = NULL;
*value = NULL;
-
+
switch (StdIO_ReadNextLine(stream, &myLine, 0, &myLineLen)) {
case StdIO_Error:
return 0;
-
+
case StdIO_EOF:
return 1;
-
+
case StdIO_Success:
if (DictLL_UnmarshalLine(myLine, myLineLen,
line, name, value) == NULL) {
@@ -386,7 +386,7 @@ DictLL_ReadLine(FILE *stream, // IN: stream to read
Bool
DictLL_MarshalLine(DynBuf *output, // IN/OUT: output buffer
- char const *name, // IN: name to marshal
+ char const *name, // IN/OPT: name to marshal
char const *value) // IN: value to marshal
{
size_t size;
diff --git a/open-vm-tools/lib/dynxdr/xdrutil.c b/open-vm-tools/lib/dynxdr/xdrutil.c
index 61e27ee2..aee24905 100644
--- a/open-vm-tools/lib/dynxdr/xdrutil.c
+++ b/open-vm-tools/lib/dynxdr/xdrutil.c
@@ -102,7 +102,7 @@ XdrUtil_Deserialize(const void *data, // IN
ASSERT(dest != NULL);
xdrmem_create(&xdrs, (char *) data, dataLen, XDR_DECODE);
- ret = (Bool) proc(&xdrs, dest);
+ ret = (Bool) proc(&xdrs, dest, 0);
xdr_destroy(&xdrs);
if (!ret) {
diff --git a/open-vm-tools/lib/err/errInt.h b/open-vm-tools/lib/err/errInt.h
index e4821c0b..f3a272b2 100644
--- a/open-vm-tools/lib/err/errInt.h
+++ b/open-vm-tools/lib/err/errInt.h
@@ -30,8 +30,8 @@
#include "err.h"
-
-const char *ErrErrno2String(Err_Number errorNumber, char *buf, size_t bufSize);
-
+const char *ErrErrno2String(Err_Number errorNumber,
+ char *buf,
+ size_t bufSize);
#endif // ifndef _ERRINT_H_
diff --git a/open-vm-tools/lib/file/file.c b/open-vm-tools/lib/file/file.c
index 4ef0903b..ba86bad4 100644
--- a/open-vm-tools/lib/file/file.c
+++ b/open-vm-tools/lib/file/file.c
@@ -58,6 +58,7 @@
#include "posix.h"
#include "file.h"
#include "fileIO.h"
+#include "util.h"
#include "fileInt.h"
#include "dynbuf.h"
#include "base64.h"
@@ -79,15 +80,15 @@
* Check if a file is accessible with the process' real user ID
*
* XXX - This function invokes access(), which uses the real uid,
- * not the effective uid, so it probably does not do what you
- * expect. Instead it should use Posix_EuidAccess(), which
+ * not the effective uid, so it probably does not do what you
+ * expect. Instead it should use Posix_EuidAccess(), which
* uses the effective uid, but it's too risky to fix right now.
* See PR 459242.
*
* Results:
* TRUE file is accessible with the process' real uid
* FALSE file doesn't exist or an error occured
- *
+ *
* Side effects:
* None
*
@@ -95,7 +96,7 @@
*/
Bool
-File_Exists(ConstUnicode pathName) // IN: May be NULL.
+File_Exists(const char *pathName) // IN: May be NULL.
{
return FileIO_IsSuccess(FileIO_Access(pathName, FILEIO_ACCESS_EXISTS));
}
@@ -106,20 +107,20 @@ File_Exists(ConstUnicode pathName) // IN: May be NULL.
*
* File_UnlinkIfExists --
*
- * If the given file exists, unlink it.
+ * If the given file exists, unlink it.
*
* Results:
- * Return 0 if the unlink is successful or if the file did not exist.
+ * Return 0 if the unlink is successful or if the file did not exist.
* Otherwise return -1.
*
* Side effects:
* May unlink the file.
- *
+ *
*----------------------------------------------------------------------
*/
int
-File_UnlinkIfExists(ConstUnicode pathName) // IN:
+File_UnlinkIfExists(const char *pathName) // IN:
{
int ret = FileDeletion(pathName, TRUE);
@@ -151,7 +152,7 @@ File_UnlinkIfExists(ConstUnicode pathName) // IN:
*/
Bool
-File_SupportsMandatoryLock(ConstUnicode pathName) // IN: file to be locked
+File_SupportsMandatoryLock(const char *pathName) // IN: file to be locked
{
/*
* For now, "know" that all ESX filesystems support mandatory locks
@@ -179,7 +180,7 @@ File_SupportsMandatoryLock(ConstUnicode pathName) // IN: file to be locked
*/
Bool
-File_IsDirectory(ConstUnicode pathName) // IN:
+File_IsDirectory(const char *pathName) // IN:
{
FileData fileData;
@@ -205,8 +206,8 @@ File_IsDirectory(ConstUnicode pathName) // IN:
*/
Bool
-File_GetFilePermissions(ConstUnicode pathName, // IN:
- int *mode) // OUT: file mode
+File_GetFilePermissions(const char *pathName, // IN:
+ int *mode) // OUT: file mode
{
FileData fileData;
@@ -255,7 +256,7 @@ File_GetFilePermissions(ConstUnicode pathName, // IN:
*/
int
-File_Unlink(ConstUnicode pathName) // IN:
+File_Unlink(const char *pathName) // IN:
{
return (FileDeletion(pathName, TRUE) == 0) ? 0 : -1;
}
@@ -280,7 +281,7 @@ File_Unlink(ConstUnicode pathName) // IN:
*/
int
-File_UnlinkNoFollow(ConstUnicode pathName) // IN:
+File_UnlinkNoFollow(const char *pathName) // IN:
{
return (FileDeletion(pathName, FALSE) == 0) ? 0 : -1;
}
@@ -303,8 +304,8 @@ File_UnlinkNoFollow(ConstUnicode pathName) // IN:
*/
Bool
-File_CreateDirectoryEx(ConstUnicode pathName, // IN:
- int mask) // IN:
+File_CreateDirectoryEx(const char *pathName, // IN:
+ int mask) // IN:
{
int err = FileCreateDirectory(pathName, mask);
@@ -329,7 +330,7 @@ File_CreateDirectoryEx(ConstUnicode pathName, // IN:
*/
Bool
-File_CreateDirectory(ConstUnicode pathName) // IN:
+File_CreateDirectory(const char *pathName) // IN:
{
return File_CreateDirectoryEx(pathName, 0777);
}
@@ -338,7 +339,7 @@ File_CreateDirectory(ConstUnicode pathName) // IN:
/*
*----------------------------------------------------------------------
*
- * File_EnsureDirectory --
+ * File_EnsureDirectoryEx --
*
* If the directory doesn't exist, creates it. If the directory
* already exists, do nothing and succeed.
@@ -353,9 +354,10 @@ File_CreateDirectory(ConstUnicode pathName) // IN:
*/
Bool
-File_EnsureDirectory(ConstUnicode pathName) // IN:
+File_EnsureDirectoryEx(const char *pathName, // IN:
+ int mask) // IN:
{
- int err = FileCreateDirectory(pathName, 0777);
+ int err = FileCreateDirectory(pathName, mask);
return ((err == 0) || (err == EEXIST));
}
@@ -364,6 +366,30 @@ File_EnsureDirectory(ConstUnicode pathName) // IN:
/*
*----------------------------------------------------------------------
*
+ * File_EnsureDirectory --
+ *
+ * If the directory doesn't exist, creates it. If the directory
+ * already exists, do nothing and succeed.
+ *
+ * Results:
+ * See above.
+ *
+ * Side effects:
+ * May create a directory on disk.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+File_EnsureDirectory(const char *pathName) // IN:
+{
+ return File_EnsureDirectoryEx(pathName, 0777);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* File_DeleteEmptyDirectory --
*
* Deletes the specified directory if it is empty.
@@ -378,7 +404,7 @@ File_EnsureDirectory(ConstUnicode pathName) // IN:
*/
Bool
-File_DeleteEmptyDirectory(ConstUnicode pathName) // IN:
+File_DeleteEmptyDirectory(const char *pathName) // IN:
{
Bool returnValue = TRUE;
@@ -634,8 +660,8 @@ OldMachineIDMatch(const char *first, // IN:
*/
Bool
-FileLockMachineIDMatch(char *hostMachineID, // IN:
- char *otherMachineID) // IN:
+FileLockMachineIDMatch(const char *hostMachineID, // IN:
+ const char *otherMachineID) // IN:
{
if (strncmp(hostMachineID, "uuid=", 5) == 0) {
if (strncmp(otherMachineID, "uuid=", 5) == 0) {
@@ -671,7 +697,7 @@ FileLockMachineIDMatch(char *hostMachineID, // IN:
*/
Bool
-File_IsEmptyDirectory(ConstUnicode pathName) // IN:
+File_IsEmptyDirectory(const char *pathName) // IN:
{
int numFiles;
@@ -712,10 +738,10 @@ File_IsEmptyDirectory(ConstUnicode pathName) // IN:
*/
Bool
-File_IsOsfsVolumeEmpty(ConstUnicode pathName) // IN:
+File_IsOsfsVolumeEmpty(const char *pathName) // IN:
{
int i, numFiles;
- Unicode *fileList = NULL;
+ char **fileList = NULL;
static const char vmfsSystemFilesuffix[] = ".sf";
Bool onlyVmfsSystemFilesFound = TRUE;
@@ -731,7 +757,7 @@ File_IsOsfsVolumeEmpty(ConstUnicode pathName) // IN:
}
}
- Unicode_FreeList(fileList, numFiles);
+ Util_FreeStringList(fileList, numFiles);
return onlyVmfsSystemFilesFound;
}
@@ -755,7 +781,7 @@ File_IsOsfsVolumeEmpty(ConstUnicode pathName) // IN:
*/
Bool
-File_IsFile(ConstUnicode pathName) // IN:
+File_IsFile(const char *pathName) // IN:
{
FileData fileData;
@@ -794,7 +820,7 @@ File_CopyFromFdToFd(FileIODescriptor src, // IN:
size_t actual;
FileIOResult fretW;
- fretR = FileIO_Read(&src, buf, sizeof(buf), &actual);
+ fretR = FileIO_Read(&src, buf, sizeof buf, &actual);
if (!FileIO_IsSuccess(fretR) && (fretR != FILEIO_READ_ERROR_EOF)) {
err = Err_Errno();
@@ -824,228 +850,6 @@ File_CopyFromFdToFd(FileIODescriptor src, // IN:
/*
- *----------------------------------------------------------------------
- *
- * File_CopyFromFdToName --
- *
- * Copy the 'src' file to 'dstName'.
- * If the 'dstName' file already exists,
- * If 'dstDispose' is -1, the user is prompted for proper action.
- * If 'dstDispose' is 0, retry until success (dangerous).
- * If 'dstDispose' is 1, overwrite the file.
- * If 'dstDispose' is 2, return the error.
- *
- * Results:
- * TRUE on success
- * FALSE on failure: if the user cancelled the operation, no message is
- * appended. Otherwise messages are appended
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-File_CopyFromFdToName(FileIODescriptor src, // IN:
- ConstUnicode dstName, // IN:
- int dstDispose) // IN:
-{
- Bool success;
- Err_Number err;
- FileIOResult fret;
- FileIODescriptor dst;
-
- ASSERT(dstName);
-
- FileIO_Invalidate(&dst);
-
- fret = File_CreatePrompt(&dst, dstName, 0, dstDispose);
- if (!FileIO_IsSuccess(fret)) {
- err = Err_Errno();
-
- if (fret != FILEIO_CANCELLED) {
- Msg_Append(MSGID(File.CopyFromFdToName.create.failure)
- "Unable to create a new '%s' file: %s.\n\n",
- UTF8(dstName), FileIO_MsgError(fret));
- }
-
- Err_SetErrno(err);
-
- return FALSE;
- }
-
- success = File_CopyFromFdToFd(src, dst);
-
- err = Err_Errno();
-
- if (FileIO_Close(&dst) != 0) {
- if (success) { // Report close failure when there isn't another error
- err = Err_Errno();
- }
-
- Msg_Append(MSGID(File.CopyFromFdToName.close.failure)
- "Unable to close the '%s' file: %s.\n\n", UTF8(dstName),
- Msg_ErrString());
-
- success = FALSE;
- }
-
- if (!success) {
- /* The copy failed: ensure the destination file is removed */
- File_Unlink(dstName);
- }
-
- Err_SetErrno(err);
-
- return success;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * File_CreatePrompt --
- *
- * Create the 'name' file for write access or 'access' access.
- * If the 'name' file already exists,
- * If 'prompt' is not -1, it is the automatic answer to the question that
- * would be asked to the user if it was -1.
- *
- * Results:
- * FILEIO_CANCELLED if the operation was cancelled by the user, otherwise
- * as FileIO_Open()
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-
-FileIOResult
-File_CreatePrompt(FileIODescriptor *file, // OUT:
- ConstUnicode pathName, // IN:
- int access, // IN:
- int prompt) // IN:
-{
- FileIOResult fret;
- FileIOOpenAction action;
-
- ASSERT(file);
- ASSERT(pathName);
-
- action = FILEIO_OPEN_CREATE_SAFE;
-
- while ((fret = FileIO_Open(file, pathName, FILEIO_OPEN_ACCESS_WRITE | access,
- action)) == FILEIO_OPEN_ERROR_EXIST) {
- static Msg_String const buttons[] = {
- {BUTTONID(file.create.retry) "Retry"},
- {BUTTONID(file.create.overwrite) "Overwrite"},
- {BUTTONID(cancel) "Cancel"},
- {NULL}
- };
- int answer;
- Err_Number err = Err_Errno();
-
- answer = (prompt != -1) ? prompt : Msg_Question(buttons, 2,
- MSGID(File.CreatePrompt.question)
- "The file '%s' already exists.\n"
- "To overwrite the content of the file, select Overwrite.\n"
- "To retry the operation after you have moved the file "
- "to another location, select Retry.\n"
- "To cancel the operation, select Cancel.\n",
- UTF8(pathName));
-
- Err_SetErrno(err);
-
- if (answer == 2) {
- fret = FILEIO_CANCELLED;
- break;
- }
- if (answer == 1) {
- action = FILEIO_OPEN_CREATE_EMPTY;
- }
- }
-
- return fret;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * File_CopyFromNameToName --
- *
- * Copy the 'srcName' file to 'dstName'.
- * If 'srcName' doesn't exist, an error is reported
- * If the 'dstName' file already exists,
- * If 'dstDispose' is -1, the user is prompted for proper action.
- * If 'dstDispose' is 0, retry until success (dangerous).
- * If 'dstDispose' is 1, overwrite the file.
- * If 'dstDispose' is 2, return the error.
- *
- * Results:
- * TRUE on success
- * FALSE on failure: if the user cancelled the operation, no message is
- * appended. Otherwise messages are appended
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-File_CopyFromNameToName(ConstUnicode srcName, // IN:
- ConstUnicode dstName, // IN:
- int dstDispose) // IN:
-{
- Bool success;
- Err_Number err;
- FileIOResult fret;
- FileIODescriptor src;
-
- ASSERT(srcName);
- ASSERT(dstName);
-
- FileIO_Invalidate(&src);
-
- fret = FileIO_Open(&src, srcName, FILEIO_OPEN_ACCESS_READ, FILEIO_OPEN);
- if (!FileIO_IsSuccess(fret)) {
- err = Err_Errno();
-
- Msg_Append(MSGID(File.CopyFromNameToName.open.failure)
- "Unable to open the '%s' file for read access: %s.\n\n",
- UTF8(srcName), FileIO_MsgError(fret));
-
- Err_SetErrno(err);
-
- return FALSE;
- }
-
- success = File_CopyFromFdToName(src, dstName, dstDispose);
-
- err = Err_Errno();
-
- if (FileIO_Close(&src) != 0) {
- if (success) { // Report close failure when there isn't another error
- err = Err_Errno();
- }
-
- Msg_Append(MSGID(File.CopyFromNameToName.close.failure)
- "Unable to close the '%s' file: %s.\n\n", UTF8(srcName),
- Msg_ErrString());
-
- success = FALSE;
- }
-
- Err_SetErrno(err);
-
- return success;
-}
-
-
-/*
*-----------------------------------------------------------------------------
*
* FileCopyTree --
@@ -1065,8 +869,8 @@ File_CopyFromNameToName(ConstUnicode srcName, // IN:
*/
static Bool
-FileCopyTree(ConstUnicode srcName, // IN:
- ConstUnicode dstName, // IN:
+FileCopyTree(const char *srcName, // IN:
+ const char *dstName, // IN:
Bool overwriteExisting, // IN:
Bool followSymlinks) // IN:
{
@@ -1074,7 +878,7 @@ FileCopyTree(ConstUnicode srcName, // IN:
Bool success = TRUE;
int numFiles;
int i;
- Unicode *fileList = NULL;
+ char **fileList = NULL;
numFiles = File_ListDirectory(srcName, &fileList);
@@ -1082,7 +886,7 @@ FileCopyTree(ConstUnicode srcName, // IN:
err = Err_Errno();
Msg_Append(MSGID(File.CopyTree.walk.failure)
"Unable to access '%s' when copying files.\n\n",
- UTF8(srcName));
+ srcName);
Err_SetErrno(err);
return FALSE;
@@ -1092,7 +896,7 @@ FileCopyTree(ConstUnicode srcName, // IN:
for (i = 0; i < numFiles && success; i++) {
struct stat sb;
- Unicode srcFilename;
+ char *srcFilename;
srcFilename = File_PathJoin(srcName, fileList[i]);
@@ -1103,7 +907,7 @@ FileCopyTree(ConstUnicode srcName, // IN:
}
if (success) {
- Unicode dstFilename = File_PathJoin(dstName, fileList[i]);
+ char *dstFilename = File_PathJoin(dstName, fileList[i]);
switch (sb.st_mode & S_IFMT) {
case S_IFDIR:
@@ -1117,8 +921,8 @@ FileCopyTree(ConstUnicode srcName, // IN:
err = Err_Errno();
Msg_Append(MSGID(File.CopyTree.symlink.failure)
"Unable to symlink '%s' to '%s': %s\n\n",
- UTF8(Posix_ReadLink(srcFilename)),
- UTF8(dstFilename),
+ Posix_ReadLink(srcFilename),
+ dstFilename,
Err_Errno2String(err));
Err_SetErrno(err);
success = FALSE;
@@ -1131,7 +935,7 @@ FileCopyTree(ConstUnicode srcName, // IN:
err = Err_Errno();
Msg_Append(MSGID(File.CopyTree.copy.failure)
"Unable to copy '%s' to '%s': %s\n\n",
- UTF8(srcFilename), UTF8(dstFilename),
+ srcFilename, dstFilename,
Err_Errno2String(err));
Err_SetErrno(err);
success = FALSE;
@@ -1140,23 +944,19 @@ FileCopyTree(ConstUnicode srcName, // IN:
break;
}
- Unicode_Free(dstFilename);
+ free(dstFilename);
} else {
err = Err_Errno();
Msg_Append(MSGID(File.CopyTree.stat.failure)
"Unable to get information on '%s' when copying files.\n\n",
- UTF8(srcFilename));
+ srcFilename);
Err_SetErrno(err);
}
- Unicode_Free(srcFilename);
- }
-
- for (i = 0; i < numFiles; i++) {
- Unicode_Free(fileList[i]);
+ free(srcFilename);
}
- free(fileList);
+ Util_FreeStringList(fileList, numFiles);
return success;
}
@@ -1181,8 +981,8 @@ FileCopyTree(ConstUnicode srcName, // IN:
*/
Bool
-File_CopyTree(ConstUnicode srcName, // IN:
- ConstUnicode dstName, // IN:
+File_CopyTree(const char *srcName, // IN:
+ const char *dstName, // IN:
Bool overwriteExisting, // IN:
Bool followSymlinks) // IN:
{
@@ -1195,7 +995,7 @@ File_CopyTree(ConstUnicode srcName, // IN:
err = Err_Errno();
Msg_Append(MSGID(File.CopyTree.source.notDirectory)
"Source path '%s' is not a directory.",
- UTF8(srcName));
+ srcName);
Err_SetErrno(err);
return FALSE;
}
@@ -1204,7 +1004,7 @@ File_CopyTree(ConstUnicode srcName, // IN:
err = Err_Errno();
Msg_Append(MSGID(File.CopyTree.dest.notDirectory)
"Destination path '%s' is not a directory.",
- UTF8(dstName));
+ dstName);
Err_SetErrno(err);
return FALSE;
}
@@ -1233,9 +1033,9 @@ File_CopyTree(ConstUnicode srcName, // IN:
*/
Bool
-File_CopyFromFd(FileIODescriptor src, // IN:
- ConstUnicode dstName, // IN:
- Bool overwriteExisting) // IN:
+File_CopyFromFd(FileIODescriptor src, // IN:
+ const char *dstName, // IN:
+ Bool overwriteExisting) // IN:
{
Bool success;
Err_Number err;
@@ -1255,7 +1055,7 @@ File_CopyFromFd(FileIODescriptor src, // IN:
err = Err_Errno();
Msg_Append(MSGID(File.CopyFromFdToName.create.failure)
- "Unable to create a new '%s' file: %s.\n\n", UTF8(dstName),
+ "Unable to create a new '%s' file: %s.\n\n", dstName,
FileIO_MsgError(fret));
Err_SetErrno(err);
@@ -1267,13 +1067,13 @@ File_CopyFromFd(FileIODescriptor src, // IN:
err = Err_Errno();
- if (FileIO_Close(&dst) != 0) {
+ if (!FileIO_IsSuccess(FileIO_Close(&dst))) {
if (success) { // Report close failure when there isn't another error
err = Err_Errno();
}
Msg_Append(MSGID(File.CopyFromFdToName.close.failure)
- "Unable to close the '%s' file: %s.\n\n", UTF8(dstName),
+ "Unable to close the '%s' file: %s.\n\n", dstName,
Msg_ErrString());
success = FALSE;
@@ -1311,8 +1111,8 @@ File_CopyFromFd(FileIODescriptor src, // IN:
*/
Bool
-File_Copy(ConstUnicode srcName, // IN:
- ConstUnicode dstName, // IN:
+File_Copy(const char *srcName, // IN:
+ const char *dstName, // IN:
Bool overwriteExisting) // IN:
{
Bool success;
@@ -1331,7 +1131,7 @@ File_Copy(ConstUnicode srcName, // IN:
Msg_Append(MSGID(File.Copy.open.failure)
"Unable to open the '%s' file for read access: %s.\n\n",
- UTF8(srcName), FileIO_MsgError(fret));
+ srcName, FileIO_MsgError(fret));
Err_SetErrno(err);
@@ -1341,14 +1141,14 @@ File_Copy(ConstUnicode srcName, // IN:
success = File_CopyFromFd(src, dstName, overwriteExisting);
err = Err_Errno();
-
- if (FileIO_Close(&src) != 0) {
+
+ if (!FileIO_IsSuccess(FileIO_Close(&src))) {
if (success) { // Report close failure when there isn't another error
err = Err_Errno();
}
Msg_Append(MSGID(File.Copy.close.failure)
- "Unable to close the '%s' file: %s.\n\n", UTF8(srcName),
+ "Unable to close the '%s' file: %s.\n\n", srcName,
Msg_ErrString());
success = FALSE;
@@ -1373,17 +1173,17 @@ File_Copy(ConstUnicode srcName, // IN:
* Results:
* TRUE succeeded
* FALSE otherwise
- *
+ *
* Side effects:
* src file is no more, but dst file exists
*
*----------------------------------------------------------------------
*/
-Bool
-File_Move(ConstUnicode oldFile, // IN:
- ConstUnicode newFile, // IN:
- Bool *asRename) // OUT: result occurred due to rename/copy
+Bool
+File_Move(const char *oldFile, // IN:
+ const char *newFile, // IN:
+ Bool *asRename) // OUT/OPT: result occurred due to rename/copy
{
Bool ret;
Bool duringRename;
@@ -1441,10 +1241,10 @@ File_Move(ConstUnicode oldFile, // IN:
*/
Bool
-File_MoveTree(ConstUnicode srcName, // IN:
- ConstUnicode dstName, // IN:
+File_MoveTree(const char *srcName, // IN:
+ const char *dstName, // IN:
Bool overwriteExisting, // IN:
- Bool *asMove) // OUT:
+ Bool *asMove) // OUT/OPT:
{
Bool ret = FALSE;
Bool createdDir = FALSE;
@@ -1459,7 +1259,7 @@ File_MoveTree(ConstUnicode srcName, // IN:
if (!File_IsDirectory(srcName)) {
Msg_Append(MSGID(File.MoveTree.source.notDirectory)
"Source path '%s' is not a directory.",
- UTF8(srcName));
+ srcName);
return FALSE;
}
@@ -1479,7 +1279,7 @@ File_MoveTree(ConstUnicode srcName, // IN:
if (ENOENT == err) {
if (!File_CreateDirectoryHierarchy(dstName, NULL)) {
Msg_Append(MSGID(File.MoveTree.dst.couldntCreate)
- "Could not create '%s'.\n\n", UTF8(dstName));
+ "Could not create '%s'.\n\n", dstName);
return FALSE;
}
@@ -1488,7 +1288,7 @@ File_MoveTree(ConstUnicode srcName, // IN:
} else {
Msg_Append(MSGID(File.MoveTree.statFailed)
"%d:Failed to stat destination '%s'.\n\n",
- err, UTF8(dstName));
+ err, dstName);
return FALSE;
}
@@ -1496,7 +1296,7 @@ File_MoveTree(ConstUnicode srcName, // IN:
if (!File_IsDirectory(dstName)) {
Msg_Append(MSGID(File.MoveTree.dest.notDirectory)
"The destination path '%s' is not a directory.\n\n",
- UTF8(dstName));
+ dstName);
return FALSE;
}
@@ -1518,7 +1318,7 @@ File_MoveTree(ConstUnicode srcName, // IN:
srcSize = File_GetSizeEx(srcName);
freeSpace = File_GetFreeSpace(dstName, TRUE);
if (freeSpace < srcSize) {
- Unicode spaceStr = Msg_FormatSizeInBytes(srcSize);
+ char *spaceStr = Msg_FormatSizeInBytes(srcSize);
Msg_Append(MSGID(File.MoveTree.dst.insufficientSpace)
"There is not enough space in the file system to "
"move the directory tree. Free %s and try again.",
@@ -1536,14 +1336,14 @@ File_MoveTree(ConstUnicode srcName, // IN:
Msg_Append(MSGID(File.MoveTree.cleanupFailed)
"Forced to copy '%s' into '%s' but unable to remove "
"source directory.\n\n",
- UTF8(srcName), UTF8(dstName));
+ srcName, dstName);
}
} else {
ret = FALSE;
Msg_Append(MSGID(File.MoveTree.copyFailed)
"Could not rename and failed to copy source directory "
"'%s'.\n\n",
- UTF8(srcName));
+ srcName);
if (createdDir) {
/*
* Only clean up if we created the directory. Not attempting to
@@ -1563,14 +1363,14 @@ File_MoveTree(ConstUnicode srcName, // IN:
*
* File_GetModTimeString --
*
- * Returns a human-readable string denoting the last modification
+ * Returns a human-readable string denoting the last modification
* time of a file.
* ctime() returns string terminated with newline, which we replace
* with a '\0'.
*
* Results:
* Last modification time string on success, NULL on error.
- *
+ *
* Side effects:
* None.
*
@@ -1578,7 +1378,7 @@ File_MoveTree(ConstUnicode srcName, // IN:
*/
char *
-File_GetModTimeString(ConstUnicode pathName) // IN:
+File_GetModTimeString(const char *pathName) // IN:
{
int64 modTime;
@@ -1605,7 +1405,7 @@ File_GetModTimeString(ConstUnicode pathName) // IN:
*/
int64
-File_GetSize(ConstUnicode pathName) // IN:
+File_GetSize(const char *pathName) // IN:
{
int64 ret;
@@ -1649,7 +1449,7 @@ File_GetSize(ConstUnicode pathName) // IN:
*/
Bool
-File_SupportsLargeFiles(ConstUnicode pathName) // IN:
+File_SupportsLargeFiles(const char *pathName) // IN:
{
return File_SupportsFileSize(pathName, CONST64U(0x100000000));
}
@@ -1673,11 +1473,11 @@ File_SupportsLargeFiles(ConstUnicode pathName) // IN:
*/
int64
-File_GetSizeEx(ConstUnicode pathName) // IN
+File_GetSizeEx(const char *pathName) // IN:
{
int numFiles;
int i;
- Unicode *fileList = NULL;
+ char **fileList = NULL;
struct stat sb;
int64 totalSize = 0;
@@ -1700,14 +1500,14 @@ File_GetSizeEx(ConstUnicode pathName) // IN
}
for (i = 0; i < numFiles; i++) {
- Unicode fileName;
+ char *fileName;
int64 fileSize;
fileName = File_PathJoin(pathName, fileList[i]);
fileSize = File_GetSizeEx(fileName);
- Unicode_Free(fileName);
+ free(fileName);
if (-1 == fileSize) {
totalSize = -1;
@@ -1717,9 +1517,7 @@ File_GetSizeEx(ConstUnicode pathName) // IN
}
}
- if (numFiles >= 0) {
- Unicode_FreeList(fileList, numFiles);
- }
+ Util_FreeStringList(fileList, numFiles);
return totalSize;
}
@@ -1742,7 +1540,7 @@ File_GetSizeEx(ConstUnicode pathName) // IN
*/
int64
-File_GetSizeByPath(ConstUnicode pathName) // IN:
+File_GetSizeByPath(const char *pathName) // IN:
{
return (pathName == NULL) ? -1 : FileIO_GetSizeByPath(pathName);
}
@@ -1766,7 +1564,7 @@ File_GetSizeByPath(ConstUnicode pathName) // IN:
* Otherwise *topmostCreated is set to the topmost directory which was
* created. *topmostCreated is set even in case of failure.
*
- * The caller most Unicode_Free the resulting string.
+ * The caller most free the resulting string.
*
* Side effects:
* Only the obvious.
@@ -1775,11 +1573,11 @@ File_GetSizeByPath(ConstUnicode pathName) // IN:
*/
Bool
-File_CreateDirectoryHierarchyEx(ConstUnicode pathName, // IN:
- int mask, // IN
- Unicode *topmostCreated) // OUT:
+File_CreateDirectoryHierarchyEx(const char *pathName, // IN:
+ int mask, // IN:
+ char **topmostCreated) // OUT/OPT:
{
- Unicode volume;
+ char *volume;
UnicodeIndex index;
UnicodeIndex length;
@@ -1805,7 +1603,7 @@ File_CreateDirectoryHierarchyEx(ConstUnicode pathName, // IN:
index = Unicode_LengthInCodePoints(volume);
- Unicode_Free(volume);
+ free(volume);
if (index >= length) {
return File_IsDirectory(pathName);
@@ -1817,23 +1615,33 @@ File_CreateDirectoryHierarchyEx(ConstUnicode pathName, // IN:
while (TRUE) {
Bool failed;
- Unicode temp;
+ char *temp;
index = FileFirstSlashIndex(pathName, index + 1);
- temp = Unicode_Substr(pathName, 0, (index == UNICODE_INDEX_NOT_FOUND) ? -1 : index);
+ temp = Unicode_Substr(pathName,
+ 0,
+ (index == UNICODE_INDEX_NOT_FOUND) ? -1 : index);
- if (File_IsDirectory(temp)) {
- failed = FALSE;
- } else {
- failed = !File_CreateDirectoryEx(temp, mask);
- if (!failed && topmostCreated != NULL && *topmostCreated == NULL) {
- *topmostCreated = temp;
- temp = NULL;
+ /*
+ * If we check if the directory already exists and then we create it,
+ * there is a race between these two operations - that might cause this
+ * operation to fail with no reason.
+ * This is why we reverse the attempt and the check.
+ */
+
+ failed = !File_CreateDirectoryEx(temp, mask);
+
+ if (failed) {
+ if (File_IsDirectory(temp)) {
+ failed = FALSE;
}
+ } else if (topmostCreated != NULL && *topmostCreated == NULL) {
+ *topmostCreated = temp;
+ temp = NULL;
}
- Unicode_Free(temp);
+ free(temp);
if (failed) {
return FALSE;
@@ -1867,7 +1675,7 @@ File_CreateDirectoryHierarchyEx(ConstUnicode pathName, // IN:
* Otherwise *topmostCreated is set to the topmost directory which was
* created. *topmostCreated is set even in case of failure.
*
- * The caller most Unicode_Free the resulting string.
+ * The caller most free the resulting string.
*
* Side effects:
* Only the obvious.
@@ -1876,43 +1684,44 @@ File_CreateDirectoryHierarchyEx(ConstUnicode pathName, // IN:
*/
Bool
-File_CreateDirectoryHierarchy(ConstUnicode pathName, // IN:
- Unicode *topmostCreated) // OUT:
+File_CreateDirectoryHierarchy(const char *pathName, // IN:
+ char **topmostCreated) // OUT/OPT:
{
return File_CreateDirectoryHierarchyEx(pathName,
0777,
topmostCreated);
}
-
/*
*----------------------------------------------------------------------
*
- * File_DeleteDirectoryTree --
+ * FileDeleteDirectoryTree --
*
* Deletes the specified directory tree. If filesystem errors are
* encountered along the way, the function will continue to delete what
- * it can but will return FALSE.
+ * it can but will return FALSE. If contentOnly is TRUE it does not
+ * delete the directory itself.
*
* Results:
* TRUE the entire tree was deleted or didn't exist
* FALSE otherwise.
- *
+ *
* Side effects:
* Deletes the directory tree from disk.
*
*----------------------------------------------------------------------
*/
-Bool
-File_DeleteDirectoryTree(ConstUnicode pathName) // IN: directory to delete
+static INLINE Bool
+FileDeleteDirectoryTree(const char *pathName, // IN: directory to delete
+ Bool contentOnly) // IN: Content only or not
{
int i;
int numFiles;
int err = 0;
- Unicode base;
+ char *base;
- Unicode *fileList = NULL;
+ char **fileList = NULL;
Bool sawFileError = FALSE;
if (Posix_EuidAccess(pathName, F_OK) != 0) {
@@ -1949,7 +1758,7 @@ File_DeleteDirectoryTree(ConstUnicode pathName) // IN: directory to delete
base = Unicode_Append(pathName, DIRSEPS);
for (i = 0; i < numFiles; i++) {
- Unicode curPath;
+ char *curPath;
struct stat statbuf;
curPath = Unicode_Append(base, fileList[i]);
@@ -1958,7 +1767,7 @@ File_DeleteDirectoryTree(ConstUnicode pathName) // IN: directory to delete
switch (statbuf.st_mode & S_IFMT) {
case S_IFDIR:
/* Directory, recurse */
- if (!File_DeleteDirectoryTree(curPath)) {
+ if (!FileDeleteDirectoryTree(curPath, FALSE)) {
sawFileError = TRUE;
}
break;
@@ -1992,30 +1801,80 @@ File_DeleteDirectoryTree(ConstUnicode pathName) // IN: directory to delete
sawFileError = TRUE;
}
- Unicode_Free(curPath);
+ free(curPath);
}
- Unicode_Free(base);
-
- /*
- * Call File_DeleteEmptyDirectory() only if there is no prior error
- * while deleting the children.
- */
- if (!sawFileError && !File_DeleteEmptyDirectory(pathName)) {
- sawFileError = TRUE;
- }
+ free(base);
- for (i = 0; i < numFiles; i++) {
- Unicode_Free(fileList[i]);
+ if (!contentOnly) {
+ /*
+ * Call File_DeleteEmptyDirectory() only if there is no prior error
+ * while deleting the children.
+ */
+ if (!sawFileError && !File_DeleteEmptyDirectory(pathName)) {
+ sawFileError = TRUE;
+ }
}
- free(fileList);
+ Util_FreeStringList(fileList, numFiles);
return !sawFileError;
}
/*
+ *----------------------------------------------------------------------
+ *
+ * File_DeleteDirectoryContent --
+ *
+ * Deletes the specified directory content. If filesystem errors are
+ * encountered along the way, the function will continue to delete what
+ * it can but will return FALSE.
+ *
+ * Results:
+ * TRUE the entire content was deleted or there were no files and the
+ * directoy was empty
+ * FALSE otherwise.
+ *
+ * Side effects:
+ * Deletes the directory content from disk.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+File_DeleteDirectoryContent(const char *pathName) // IN: directory to delete
+{
+ return FileDeleteDirectoryTree(pathName, TRUE);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * File_DeleteDirectoryTree --
+ *
+ * Deletes the specified directory tree. If filesystem errors are
+ * encountered along the way, the function will continue to delete what
+ * it can but will return FALSE.
+ *
+ * Results:
+ * TRUE the entire tree was deleted or didn't exist
+ * FALSE otherwise.
+ *
+ * Side effects:
+ * Deletes the directory tree from disk.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+File_DeleteDirectoryTree(const char *pathName) // IN: directory to delete
+{
+ return FileDeleteDirectoryTree(pathName, FALSE);
+}
+
+/*
*-----------------------------------------------------------------------------
*
* File_FindFileInSearchPath --
@@ -2037,7 +1896,7 @@ Bool
File_FindFileInSearchPath(const char *fileIn, // IN:
const char *searchPath, // IN:
const char *cwd, // IN:
- char **result) // OUT:
+ char **result) // OUT/OPT:
{
char *cur;
char *tok;
@@ -2045,8 +1904,8 @@ File_FindFileInSearchPath(const char *fileIn, // IN:
Bool full;
char *saveptr = NULL;
char *sp = NULL;
- Unicode dir = NULL;
- Unicode file = NULL;
+ char *dir = NULL;
+ char *file = NULL;
ASSERT(fileIn);
ASSERT(cwd);
@@ -2141,8 +2000,8 @@ done:
}
free(sp);
- Unicode_Free(dir);
- Unicode_Free(file);
+ free(dir);
+ free(file);
return found;
}
@@ -2275,7 +2134,7 @@ FileSleeper(uint32 msecMinSleepTime, // IN:
msecActualSleepTime = msecMinSleepTime + (uint32) (fpRand * variance);
}
- usleep(1000 * msecActualSleepTime);
+ Util_Usleep(1000 * msecActualSleepTime);
return msecActualSleepTime;
}
@@ -2482,12 +2341,10 @@ FileRotateByRenumber(const char *filePath, // IN: full path to file
}
}
- if (newFilePath != NULL) {
- if (result == -1) {
- free(tmp);
- } else {
- *newFilePath = tmp;
- }
+ if (newFilePath == NULL || result == -1) {
+ free(tmp);
+ } else {
+ *newFilePath = tmp;
}
if (nFound >= n) {
@@ -2544,6 +2401,8 @@ File_Rotate(const char *fileName, // IN: original file
size_t baseLen;
char *baseName;
+ ASSERT(fileName);
+
if ((ext = Str_Strrchr(fileName, '.')) == NULL) {
ext = fileName + strlen(fileName);
}
@@ -2586,8 +2445,8 @@ File_Rotate(const char *fileName, // IN: original file
*-----------------------------------------------------------------------------
*/
-int
-File_GetFSMountInfo(ConstUnicode pathName,
+int
+File_GetFSMountInfo(const char *pathName,
char **fsType,
uint32 *version,
char **remoteIP,
@@ -2598,7 +2457,7 @@ File_GetFSMountInfo(ConstUnicode pathName,
return File_GetVMFSMountInfo(pathName, fsType, version,
remoteIP, remoteMountPoint,
localMountPoint);
-#else
+#else
return -1;
#endif
}
diff --git a/open-vm-tools/lib/file/fileIO.c b/open-vm-tools/lib/file/fileIO.c
index f5db24e6..973ee968 100644
--- a/open-vm-tools/lib/file/fileIO.c
+++ b/open-vm-tools/lib/file/fileIO.c
@@ -111,7 +111,7 @@ FileIO_MsgError(FileIOResult status) // IN
* because you don't want to display error messages after a user has
* cancelled an operation.
*/
- result = MSGID(fileio.cancel) "The operation was canceled by the user";
+ result = MSGID(fileio.cancel) "The operation was cancelled by the user";
break;
case FILEIO_ERROR:
@@ -198,8 +198,8 @@ FileIO_MsgError(FileIOResult status) // IN
*/
void
-FileIO_Init(FileIODescriptor *fd, // IN/OUT:
- ConstUnicode pathName) // IN:
+FileIO_Init(FileIODescriptor *fd, // IN/OUT:
+ const char *pathName) // IN:
{
ASSERT(fd);
ASSERT(pathName);
@@ -231,7 +231,7 @@ FileIO_Cleanup(FileIODescriptor *fd) // IN/OUT:
ASSERT(fd);
if (fd->fileName) {
- Unicode_Free(fd->fileName);
+ free(fd->fileName);
fd->fileName = NULL;
}
}
@@ -341,7 +341,7 @@ FileIO_Lock(FileIODescriptor *file, // IN/OUT:
if (file->lockToken == NULL) {
/* Describe the lock not acquired situation in detail */
Warning(LGPFX" %s on '%s' failed: %s\n",
- __FUNCTION__, UTF8(file->fileName),
+ __FUNCTION__, file->fileName,
(err == 0) ? "Lock timed out" : strerror(err));
/* Return a serious failure status if the locking code did */
@@ -400,7 +400,7 @@ FileIO_Unlock(FileIODescriptor *file) // IN/OUT:
if (!FileLock_Unlock(file->lockToken, &err, NULL)) {
Warning(LGPFX" %s on '%s' failed: %s\n",
- __FUNCTION__, UTF8(file->fileName), strerror(err));
+ __FUNCTION__, file->fileName, strerror(err));
ret = FILEIO_ERROR;
}
@@ -446,7 +446,7 @@ FileIO_GetSize(const FileIODescriptor *fd) // IN:
*
* FileIO_GetSizeByPath --
*
- * Get size of a file specified by path.
+ * Get size of a file specified by path.
*
* Results:
* Size of file or -1.
@@ -458,7 +458,7 @@ FileIO_GetSize(const FileIODescriptor *fd) // IN:
*/
int64
-FileIO_GetSizeByPath(ConstUnicode pathName) // IN:
+FileIO_GetSizeByPath(const char *pathName) // IN:
{
int64 logicalBytes;
@@ -485,7 +485,7 @@ FileIO_GetSizeByPath(ConstUnicode pathName) // IN:
*----------------------------------------------------------------------
*/
-ConstUnicode
+const char *
FileIO_Filename(FileIODescriptor *fd) // IN:
{
ASSERT(fd);
@@ -502,8 +502,9 @@ FileIO_Filename(FileIODescriptor *fd) // IN:
* Closes and unlinks the file associated with a FileIODescriptor.
*
* Results:
- * TRUE: An error occurred.
- * FALSE: The file was closed and unlinked.
+ * FILEIO_SUCCESS: The file was closed and unlinked. The FileIODescriptor
+ * is no longer valid.
+ * FILEIO_ERROR: An error occurred.
*
* Side effects:
* File is probably closed and unlinked.
@@ -511,11 +512,11 @@ FileIO_Filename(FileIODescriptor *fd) // IN:
*----------------------------------------------------------------------
*/
-Bool
+FileIOResult
FileIO_CloseAndUnlink(FileIODescriptor *fd) // IN:
{
- Unicode path;
- Bool ret;
+ char *path;
+ FileIOResult ret;
ASSERT(fd);
ASSERT(FileIO_IsValid(fd));
@@ -523,13 +524,13 @@ FileIO_CloseAndUnlink(FileIODescriptor *fd) // IN:
path = Unicode_Duplicate(fd->fileName);
ret = FileIO_Close(fd);
- if (!ret) {
+ if (FileIO_IsSuccess(ret)) {
if (File_UnlinkIfExists(path) == -1) {
- ret = TRUE;
+ ret = FILEIO_ERROR;
}
}
- Unicode_Free(path);
+ free(path);
return ret;
}
@@ -648,7 +649,7 @@ FileIO_IsSuccess(FileIOResult res) // IN:
* The caller must free the path when done.
*
* Results:
- * Unicode path if successful, NULL on failure.
+ * UTF8 path if successful, NULL on failure.
*
* Side effects:
* None.
@@ -656,11 +657,11 @@ FileIO_IsSuccess(FileIOResult res) // IN:
*-----------------------------------------------------------------------------
*/
-Unicode
-FileIO_AtomicTempPath(ConstUnicode path) // IN:
+char *
+FileIO_AtomicTempPath(const char *path) // IN:
{
- Unicode srcPath;
- Unicode retPath;
+ char *srcPath;
+ char *retPath;
srcPath = File_FullPath(path);
if (!srcPath) {
@@ -668,7 +669,7 @@ FileIO_AtomicTempPath(ConstUnicode path) // IN:
return NULL;
}
retPath = Unicode_Join(srcPath, "~", NULL);
- Unicode_Free(srcPath);
+ free(srcPath);
return retPath;
}
@@ -679,7 +680,7 @@ FileIO_AtomicTempPath(ConstUnicode path) // IN:
*
* FileIO_AtomicTempFile
*
- * Create a temp file in the same directory as the argument file.
+ * Create a temp file in the same directory as the argument file.
* On non-Windows attempts to create the temp file with the same
* permissions and owner/group as the argument file.
*
@@ -696,7 +697,7 @@ FileIOResult
FileIO_AtomicTempFile(FileIODescriptor *fileFD, // IN:
FileIODescriptor *tempFD) // OUT:
{
- Unicode tempPath = NULL;
+ char *tempPath = NULL;
int permissions;
FileIOResult status;
#if !defined(_WIN32)
@@ -769,7 +770,7 @@ FileIO_AtomicTempFile(FileIODescriptor *fileFD, // IN:
}
#endif
- Unicode_Free(tempPath);
+ free(tempPath);
return FILEIO_SUCCESS;
bail:
@@ -787,7 +788,7 @@ bail:
ASSERT(ret == 0);
#endif
}
- Unicode_Free(tempPath);
+ free(tempPath);
return status;
}
@@ -864,20 +865,20 @@ FileIO_AtomicUpdate(FileIODescriptor *newFD, // IN/OUT: file IO descriptor
File_GetPathName(newPath, &dirName, &fileName);
File_GetPathName(currPath, &dstDirName, &dstFileName);
- ASSERT(dirName && *dirName);
+ ASSERT(dirName);
ASSERT(fileName && *fileName);
- ASSERT(dstDirName && *dstDirName);
+ ASSERT(dstDirName);
ASSERT(dstFileName && *dstFileName);
- ASSERT(!strcmp(dirName, dstDirName));
+ ASSERT(File_IsSameFile(dirName, dstDirName));
- args = (FS_SwapFilesArgs *) Util_SafeCalloc(1, sizeof(*args));
- if (Str_Snprintf(args->srcFile, sizeof(args->srcFile), "%s",
+ args = Util_SafeCalloc(1, sizeof *args);
+ if (Str_Snprintf(args->srcFile, sizeof args->srcFile, "%s",
fileName) < 0) {
Log("%s: Path too long \"%s\".\n", __FUNCTION__, fileName);
savedErrno = ENAMETOOLONG;
goto swapdone;
}
- if (Str_Snprintf(args->dstFilePath, sizeof(args->dstFilePath), "%s/%s",
+ if (Str_Snprintf(args->dstFilePath, sizeof args->dstFilePath, "%s/%s",
dstDirName, dstFileName) < 0) {
Log("%s: Path too long \"%s\".\n", __FUNCTION__, dstFileName);
savedErrno = ENAMETOOLONG;
@@ -889,6 +890,12 @@ FileIO_AtomicUpdate(FileIODescriptor *newFD, // IN/OUT: file IO descriptor
* because the file could be open.
*/
+ if (!*dirName) {
+ /* need a proper root directory string for Posix_Open() */
+ free(dirName);
+ dirName = Util_SafeStrdup("/");
+ }
+
fd = Posix_Open(dirName, O_RDONLY);
if (fd < 0) {
Log("%s: Open failed \"%s\" %d.\n", __FUNCTION__, dirName, errno);
@@ -1007,8 +1014,8 @@ swapdone:
currFD->win32 = tmpFD.win32;
FileIO_Cleanup(&tmpFD);
- Unicode_Free(currPath);
- Unicode_Free(newPath);
+ free(currPath);
+ free(newPath);
errno = savedErrno;
return ret;
diff --git a/open-vm-tools/lib/file/fileIOPosix.c b/open-vm-tools/lib/file/fileIOPosix.c
index bd3991f9..18aa6412 100644
--- a/open-vm-tools/lib/file/fileIOPosix.c
+++ b/open-vm-tools/lib/file/fileIOPosix.c
@@ -23,9 +23,12 @@
*/
-#if !defined(VMX86_TOOLS) && !defined(__APPLE__) && !defined(sun)
-#define FILEIO_SUPPORT_ODIRECT
-#define _GNU_SOURCE
+#if defined(__linux__)
+# if !defined(VMX86_TOOLS) && !defined(__ANDROID__)
+# define FILEIO_SUPPORT_ODIRECT
+# define _GNU_SOURCE
+# endif
+# include <features.h>
#endif
#include <stdio.h>
@@ -39,28 +42,13 @@
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
-#if defined(linux)
-/*
- * These headers are needed to get __USE_LARGEFILE, __USE_LARGEFILE64,
- * and SYS__llseek.
- */
-# ifdef ANDROID_X86
-# undef _GNU_SOURCE
-# endif
-# include <features.h>
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-# endif
-# include <linux/unistd.h>
+#if defined(__linux__)
#ifdef __ANDROID__
# include <sys/syscall.h>
#else
# include <syscall.h>
#endif
#endif
-#if defined __ANDROID__
-# include <sys/syscall.h>
-#endif
#include <sys/stat.h>
#include "su.h"
@@ -83,7 +71,7 @@
#include <sys/mount.h>
#else
#include <sys/statfs.h>
-#if !defined(sun)
+#if !defined(__sun__)
#include <mntent.h>
#include <dlfcn.h>
#endif
@@ -217,13 +205,18 @@ static AlignedPool alignedPool;
* are not available in any header file.
*/
-#if defined(__linux__)
+#if defined(__linux__) && !defined(__ANDROID__)
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
+ /*
+ * We want preadv/pwritev. But due to FOB=64, the symbols are -64.
+ * TODO: when the baseline bumps to XOPEN=700, link directly to
+ * the symbols (and anyone building XOPEN<700 gets nothing).
+ */
extern ssize_t preadv64(int fd, const struct iovec *iov, int iovcnt,
- off64_t offset) __attribute__ ((weak));
-
+ __off64_t offset) __attribute__ ((weak));
+
extern ssize_t pwritev64(int fd, const struct iovec *iov, int iovcnt,
- off64_t offset) __attribute__ ((weak));
+ __off64_t offset) __attribute__ ((weak));
#else
#error "Large file support unavailable. Aborting."
#endif
@@ -480,8 +473,8 @@ FileIO_CreateFDPosix(int posix, // IN: UNIX file descriptor
*/
Bool
-FileIO_GetVolumeSectorSize(ConstUnicode pathName, // IN:
- uint32 *sectorSize) // OUT:
+FileIO_GetVolumeSectorSize(const char *pathName, // IN:
+ uint32 *sectorSize) // OUT:
{
ASSERT(sectorSize);
@@ -599,7 +592,7 @@ ProxyReceiveResults(int sock_fd, // IN:
if (msg.msg_controllen == 0) {
*recv_fd = -1;
} else {
- cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg = CMSG_FIRSTHDR(&msg);
if ((cmsg->cmsg_level == SOL_SOCKET) &&
(cmsg->cmsg_type == SCM_RIGHTS)) {
@@ -630,9 +623,9 @@ ProxyReceiveResults(int sock_fd, // IN:
*/
static int
-ProxyOpen(ConstUnicode pathName, // IN:
- int flags, // IN:
- int mode) // IN:
+ProxyOpen(const char *pathName, // IN:
+ int flags, // IN:
+ int mode) // IN:
{
int err;
pid_t pid;
@@ -700,10 +693,10 @@ bail:
*/
static int
-ProxyUse(ConstUnicode pathName, // IN:
- Bool *useProxy) // IN:
+ProxyUse(const char *pathName, // IN:
+ Bool *useProxy) // IN:
{
- Unicode path;
+ char *path;
UnicodeIndex index;
struct statfs sfbuf;
struct stat statbuf;
@@ -729,11 +722,11 @@ ProxyUse(ConstUnicode pathName, // IN:
if (index == UNICODE_INDEX_NOT_FOUND) {
path = Unicode_Duplicate(".");
} else {
- Unicode temp;
+ char *temp;
temp = Unicode_Substr(pathName, 0, index + 1);
path = Unicode_Append(temp, ".");
- Unicode_Free(temp);
+ free(temp);
}
/*
@@ -755,7 +748,7 @@ ProxyUse(ConstUnicode pathName, // IN:
*useProxy = TRUE;
}
- Unicode_Free(path);
+ free(path);
return 0;
}
@@ -784,9 +777,9 @@ ProxyUse(ConstUnicode pathName, // IN:
*/
int
-PosixFileOpener(ConstUnicode pathName, // IN:
- int flags, // IN:
- mode_t mode) // IN:
+PosixFileOpener(const char *pathName, // IN:
+ int flags, // IN:
+ mode_t mode) // IN:
{
Bool useProxy;
@@ -795,8 +788,8 @@ PosixFileOpener(ConstUnicode pathName, // IN:
/*
* Open for write and/or O_CREAT. Determine proxy usage.
- */
-
+ */
+
err = ProxyUse(pathName, &useProxy);
if (err != 0) {
errno = err;
@@ -839,7 +832,7 @@ PosixFileOpener(ConstUnicode pathName, // IN:
FileIOResult
FileIOCreateRetry(FileIODescriptor *file, // OUT:
- ConstUnicode pathName, // IN:
+ const char *pathName, // IN:
int access, // IN:
FileIOOpenAction action, // IN:
int mode, // IN: mode_t for creation
@@ -924,7 +917,7 @@ FileIOCreateRetry(FileIODescriptor *file, // OUT:
#elif !defined(__APPLE__) // Mac hosts need this access flag after opening.
access &= ~FILEIO_OPEN_UNBUFFERED;
LOG_ONCE((LGPFX" %s reverting to buffered IO on %s.\n",
- __FUNCTION__, UTF8(pathName)));
+ __FUNCTION__, pathName));
#endif
}
@@ -942,7 +935,7 @@ FileIOCreateRetry(FileIODescriptor *file, // OUT:
}
#endif
-#if defined(linux)
+#if defined(__linux__)
if (access & FILEIO_OPEN_SYNC) {
flags |= O_SYNC;
}
@@ -1053,7 +1046,7 @@ error:
FileIOResult
FileIO_Create(FileIODescriptor *file, // OUT:
- ConstUnicode pathName, // IN:
+ const char *pathName, // IN:
int access, // IN:
FileIOOpenAction action, // IN:
int mode) // IN: mode_t for creation
@@ -1083,7 +1076,7 @@ FileIO_Create(FileIODescriptor *file, // OUT:
FileIOResult
FileIO_Open(FileIODescriptor *file, // OUT:
- ConstUnicode pathName, // IN:
+ const char *pathName, // IN:
int access, // IN:
FileIOOpenAction action) // IN:
{
@@ -1113,43 +1106,36 @@ FileIO_Open(FileIODescriptor *file, // OUT:
FileIOResult
FileIO_OpenRetry(FileIODescriptor *file, // OUT:
- ConstUnicode pathName, // IN:
+ const char *pathName, // IN:
int access, // IN:
FileIOOpenAction action, // IN:
uint32 msecMaxWaitTime) // IN:
{
#if defined(VMX86_SERVER)
FileIOResult res;
- int retries = 10;
+ uint32 msecWaitTime = 0;
+ uint32 msecMaxLoopTime = 3000; // 3 seconds
/*
* Workaround the ESX NFS client bug as seen in PR 1341775.
- * Since ESX NFS client can sometimes *wrongly* return ESTALE for
- * legitimate file open case, we retry a few times in case we hit
- * that problem.
+ * Since ESX NFS client can sometimes *wrongly* return ESTALE for a
+ * legitimate file open case, we retry for some time in hopes that the
+ * problem will resolve itself.
*/
- while (retries-- > 0) {
+
+ while (TRUE) {
res = FileIOCreateRetry(file, pathName, access, action,
S_IRUSR | S_IWUSR, msecMaxWaitTime);
- if (res == FILEIO_ERROR && Err_Errno() == ESTALE) {
- /*
- * 300 msec * 10 retries, gives us 3 secs of retry. This should
- * be good enough as the ESTALE seen in PR 1341775 is due to a
- * tiny race where another host is atomically swapping the file,
- * and causing the file to be temporarily unlinked, while this host
- * tries to open it. It should be very short lived.
- */
- if (retries > 0) {
- Log(LGPFX "FileIOCreateRetry (%s) failed with ESTALE, retrying, "
- "retries left (#%d)\n", UTF8(pathName), retries);
- Util_Usleep(300 * 1000);
- continue;
- } else {
- Log(LGPFX "Failing FileIO_OpenRetry (%s) with ESTALE!\n",
- UTF8(pathName));
- }
+
+ if (res == FILEIO_ERROR && Err_Errno() == ESTALE &&
+ msecWaitTime < msecMaxLoopTime) {
+ Log(LGPFX "FileIOCreateRetry (%s) failed with ESTALE, retrying.\n",
+ pathName);
+
+ msecWaitTime += FileSleeper(100, 300);
+ } else {
+ break;
}
- break;
}
return res;
@@ -1179,25 +1165,6 @@ FileIO_OpenRetry(FileIODescriptor *file, // OUT:
*----------------------------------------------------------------------
*/
-#if defined(linux) && defined(SYS__llseek)
-/*
- * If the llseek system call exists, use it to provide a version of 64-bit
- * lseek() functionality, for FileIO_Seek() to use if appropriate.
- */
-
-#define VM_HAVE__LLSEEK 1
-
-static INLINE int
-_llseek(unsigned int fd,
- unsigned long offset_high,
- unsigned long offset_low,
- loff_t * result,
- unsigned int whence)
-{
- return syscall(SYS__llseek, fd, offset_high, offset_low, result, whence);
-}
-#endif
-
uint64
FileIO_Seek(const FileIODescriptor *file, // IN:
int64 distance, // IN:
@@ -1205,57 +1172,19 @@ FileIO_Seek(const FileIODescriptor *file, // IN:
{
ASSERT(file);
+#if defined(__ANDROID__)
/*
- * The goal is to use the best lseek-type function with support for 64-bit
- * file offsets (aka large file support, or LFS).
- *
- * __USE_LARGEFILE implies that lseek() has LFS
- * VM_HAVE__LLSEEK tells us that we have the _llseek() routine available
- * __USE_LARGEFILE64 implies that lseek64() is available
- *
- * All three of these defines only come into play on Linux systems. On any
- * other OS, they won't be present, and we go straight for lseek() since
- * that's the only known alternative.
- */
-#if defined(VM_HAVE__LLSEEK) && !defined(__USE_LARGEFILE) && !defined(__USE_LARGEFILE64)
- /*
- * This is a Linux system that doesn't have a glibc with any large-file
- * support (LFS), but does have the llseek system call. On Linux, this is
- * the least desirable option because the API is a bit grotty (e.g. the
- * casting of negative offsets into unsigned offset_hi and offset_lo), and
- * because doing system calls directly from our code is more likely to
- * break than using libc.
+ * Android doesn't implement _FILE_OFFSET_BITS=64, but always has lseek64.
*/
-
- loff_t res;
-
- if (_llseek(file->posix, distance >> 32, distance & 0xFFFFFFFF,
- &res, FileIO_SeekOrigins[origin]) == -1) {
- res = -1;
- }
-
- return res;
-#elif defined(__USE_LARGEFILE64) && !defined(__USE_LARGEFILE)
+ return lseek64(file->posix, distance, FileIO_SeekOrigins[origin]);
+#else
/*
- * This is a Linux system with glibc that has lseek64 available, but not a
- * lseek with LFS.
- *
- * lseek64 is a bit cleaner than _llseek (because glibc provides it, we
- * know the API won't break) but still not as portable as plain old lseek.
+ * Require 64-bit file API support via _FILE_OFFSET_BITS=64 or
+ * operating system default.
*/
+ ASSERT_ON_COMPILE(sizeof(off_t) == 8);
- return lseek64(file->posix, distance, FileIO_SeekOrigins[origin]);
-#else
- /*
- * We're taking this route because either we know lseek() can support
- * 64-bit file offsets (__USE_LARGEFILE is set) or because llseek and
- * lseek64 are both unavailable.
- *
- * This means this a Linux/glibc system with transparent LFS support, an
- * old Linux system without llseek, or another POSIX system.
- */
-
- return lseek(file->posix, distance, FileIO_SeekOrigins[origin]);
+ return lseek(file->posix, distance, FileIO_SeekOrigins[origin]);
#endif
}
@@ -1336,7 +1265,7 @@ FileIO_Write(FileIODescriptor *fd, // IN:
*
* Results:
* FILEIO_SUCCESS on success: '*actual_count' = 'requested' bytes have
- * been read.
+ * been read.
* FILEIO_READ_ERROR_EOF if the end of the file was reached: only
* '*actual_count' bytes have been read for sure.
* FILEIO_ERROR for other errors: only '*actual_count' bytes have been
@@ -1429,8 +1358,9 @@ FileIO_Truncate(FileIODescriptor *file, // IN:
* Close a file
*
* Results:
- * TRUE: an error occured
- * FALSE: no error occured
+ * FILEIO_SUCCESS: The file was closed and unlinked. The FileIODescriptor
+ * is no longer valid.
+ * FILEIO_ERROR: An error occurred.
*
* Side effects:
* None
@@ -1438,7 +1368,7 @@ FileIO_Truncate(FileIODescriptor *file, // IN:
*----------------------------------------------------------------------
*/
-Bool
+FileIOResult
FileIO_Close(FileIODescriptor *file) // IN:
{
int err;
@@ -1456,7 +1386,7 @@ FileIO_Close(FileIODescriptor *file) // IN:
errno = err;
}
- return err != 0;
+ return (err == 0) ? FILEIO_SUCCESS : FILEIO_ERROR;
}
@@ -1468,8 +1398,8 @@ FileIO_Close(FileIODescriptor *file) // IN:
* Synchronize the disk state of a file with its memory state
*
* Results:
- * On success: 0
- * On failure: -1
+ * On success: FILEIO_SUCCESS
+ * On failure: FILEIO_ERROR
*
* Side effects:
* None
@@ -1477,12 +1407,12 @@ FileIO_Close(FileIODescriptor *file) // IN:
*----------------------------------------------------------------------
*/
-int
+FileIOResult
FileIO_Sync(const FileIODescriptor *file) // IN:
{
ASSERT(file);
- return fsync(file->posix);
+ return (fsync(file->posix) == -1) ? FILEIO_ERROR : FILEIO_SUCCESS;
}
@@ -1510,13 +1440,13 @@ FileIO_Sync(const FileIODescriptor *file) // IN:
*/
static Bool
-FileIOCoalesce(struct iovec *inVec, // IN: Vector to coalesce from
- int inCount, // IN: count for inVec
- size_t inTotalSize, // IN: totalSize (bytes) in inVec
- Bool isWrite, // IN: coalesce for writing (or reading)
- Bool forceCoalesce, // IN: if TRUE always coalesce
- int flags, // IN: fileIO open flags
- struct iovec *outVec) // OUT: Coalesced (1-entry) iovec
+FileIOCoalesce(struct iovec const *inVec, // IN: Vector to coalesce from
+ int inCount, // IN: count for inVec
+ size_t inTotalSize, // IN: totalSize (bytes) in inVec
+ Bool isWrite, // IN: coalesce for writing (or reading)
+ Bool forceCoalesce, // IN: if TRUE always coalesce
+ int flags, // IN: fileIO open flags
+ struct iovec *outVec) // OUT: Coalesced (1-entry) iovec
{
uint8 *cBuf;
@@ -1585,12 +1515,12 @@ FileIOCoalesce(struct iovec *inVec, // IN: Vector to coalesce from
*/
static void
-FileIODecoalesce(struct iovec *coVec, // IN: Coalesced (1-entry) vector
- struct iovec *origVec, // IN: Original vector
- int origVecCount, // IN: count for origVec
- size_t actualSize, // IN: # bytes to transfer back to origVec
- Bool isWrite, // IN: decoalesce for writing (or reading)
- int flags) // IN: fileIO open flags
+FileIODecoalesce(struct iovec *coVec, // IN: Coalesced (1-entry) vector
+ struct iovec const *origVec, // IN: Original vector
+ int origVecCount, // IN: count for origVec
+ size_t actualSize, // IN: # bytes to transfer back to origVec
+ Bool isWrite, // IN: decoalesce for writing (or reading)
+ int flags) // IN: fileIO open flags
{
ASSERT(coVec);
ASSERT(origVec);
@@ -1635,7 +1565,7 @@ FileIODecoalesce(struct iovec *coVec, // IN: Coalesced (1-entry) vector
FileIOResult
FileIO_Readv(FileIODescriptor *fd, // IN:
- struct iovec *v, // IN:
+ struct iovec const *v, // IN:
int numEntries, // IN:
size_t totalSize, // IN:
size_t *actual) // OUT:
@@ -1644,7 +1574,7 @@ FileIO_Readv(FileIODescriptor *fd, // IN:
FileIOResult fret = FILEIO_ERROR;
int nRetries = 0, maxRetries = numEntries;
struct iovec coV;
- struct iovec *vPtr;
+ struct iovec const *vPtr;
Bool didCoalesce;
int numVec;
@@ -1748,7 +1678,7 @@ FileIO_Readv(FileIODescriptor *fd, // IN:
FileIOResult
FileIO_Writev(FileIODescriptor *fd, // IN:
- struct iovec *v, // IN:
+ struct iovec const *v, // IN:
int numEntries, // IN:
size_t totalSize, // IN:
size_t *actual) // OUT:
@@ -1757,7 +1687,7 @@ FileIO_Writev(FileIODescriptor *fd, // IN:
FileIOResult fret = FILEIO_ERROR;
int nRetries = 0, maxRetries = numEntries;
struct iovec coV;
- struct iovec *vPtr;
+ struct iovec const *vPtr;
Bool didCoalesce;
int numVec;
@@ -1821,7 +1751,7 @@ FileIO_Writev(FileIODescriptor *fd, // IN:
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||\
- defined(sun)
+ defined(__sun__)
/*
*----------------------------------------------------------------------
@@ -1844,14 +1774,14 @@ FileIO_Writev(FileIODescriptor *fd, // IN:
*/
static FileIOResult
-FileIOPreadvCoalesced(FileIODescriptor *fd, // IN: File descriptor
- struct iovec *entries, // IN: Vector to read into
- int numEntries, // IN: Number of vector entries
- uint64 offset, // IN: Offset to start reading
- size_t totalSize, // IN: totalSize(bytes) in entries
- size_t *actual) // OUT: number of bytes read
+FileIOPreadvCoalesced(FileIODescriptor *fd, // IN: File descriptor
+ struct iovec const *entries, // IN: Vector to read into
+ int numEntries, // IN: Number of vector entries
+ uint64 offset, // IN: Offset to start reading
+ size_t totalSize, // IN: totalSize(bytes) in entries
+ size_t *actual) // OUT: number of bytes read
{
- struct iovec *vPtr;
+ struct iovec const *vPtr;
struct iovec coV;
int count;
uint64 fileOffset;
@@ -1932,16 +1862,16 @@ exit:
*/
static FileIOResult
-FileIOPwritevCoalesced(FileIODescriptor *fd, // IN: File descriptor
- struct iovec *entries, // IN: Vector to write from
- int numEntries, // IN: Number of vector entries
- uint64 offset, // IN: Offset to start writing
- size_t totalSize, // IN: Total size(bytes)
- size_t *actual) // OUT: number of bytes written
+FileIOPwritevCoalesced(FileIODescriptor *fd, // IN: File descriptor
+ struct iovec const *entries, // IN: Vector to write from
+ int numEntries, // IN: Number of vector entries
+ uint64 offset, // IN: Offset to start writing
+ size_t totalSize, // IN: Total size(bytes)
+ size_t *actual) // OUT: number of bytes written
{
struct iovec coV;
Bool didCoalesce;
- struct iovec *vPtr;
+ struct iovec const *vPtr;
int count;
uint64 fileOffset;
FileIOResult fret;
@@ -2009,10 +1939,10 @@ exit:
}
#endif /* defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||
- defined(sun) */
+ defined(__sun__) */
-#if defined(__linux__)
+#if defined(__linux__) && !defined(__ANDROID__)
/*
*----------------------------------------------------------------------
@@ -2045,14 +1975,14 @@ exit:
*/
static FileIOResult
-FileIOPreadvInternal(FileIODescriptor *fd, // IN: File descriptor
- struct iovec *entries, // IN: Vector to read into
- int numEntries, // IN: Number of vector entries
- uint64 offset, // IN: Offset to start reading
- size_t totalSize, // IN: totalSize(bytes) in entries
- size_t *actual) // OUT: number of bytes read
+FileIOPreadvInternal(FileIODescriptor *fd, // IN: File descriptor
+ struct iovec const *entries, // IN: Vector to read into
+ int numEntries, // IN: Number of vector entries
+ uint64 offset, // IN: Offset to start reading
+ size_t totalSize, // IN: totalSize(bytes) in entries
+ size_t *actual) // OUT: number of bytes read
{
- struct iovec *vPtr;
+ struct iovec const *vPtr;
int numVec;
size_t partialBytes = 0;
size_t bytesRead = 0;
@@ -2180,14 +2110,14 @@ FileIOPreadvInternal(FileIODescriptor *fd, // IN: File descriptor
*/
static FileIOResult
-FileIOPwritevInternal(FileIODescriptor *fd, // IN: File descriptor
- struct iovec *entries, // IN: Vector to write from
- int numEntries, // IN: Number of vector entries
- uint64 offset, // IN: Offset to start writing
- size_t totalSize, // IN: Total size(bytes)in entries
- size_t *actual) // OUT: number of bytes written
+FileIOPwritevInternal(FileIODescriptor *fd, // IN: File descriptor
+ struct iovec const *entries, // IN: Vector to write from
+ int numEntries, // IN: Number of vector entries
+ uint64 offset, // IN: Offset to start writing
+ size_t totalSize, // IN: Total size(bytes)in entries
+ size_t *actual) // OUT: number of bytes written
{
- struct iovec *vPtr;
+ struct iovec const *vPtr;
int numVec;
size_t partialBytes = 0;
size_t bytesWritten = 0;
@@ -2266,18 +2196,18 @@ FileIOPwritevInternal(FileIODescriptor *fd, // IN: File descriptor
return fret;
}
-#endif /* defined(__linux__) */
+#endif /* defined(__linux__) && !defined(__ANDROID__) */
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||\
- defined(sun)
+ defined(__sun__)
/*
*----------------------------------------------------------------------
*
* FileIO_Preadv --
*
- * Implementation of vector pread.The function checks for the support
+ * Implementation of vector pread. The function checks for the support
* of system call preadv with the version of glibc and calls the
* optimized system call. If the system call is not supported,
* we fall back to the earlier technique of coalescing the vectors
@@ -2293,12 +2223,12 @@ FileIOPwritevInternal(FileIODescriptor *fd, // IN: File descriptor
*/
FileIOResult
-FileIO_Preadv(FileIODescriptor *fd, // IN: File descriptor
- struct iovec *entries, // IN: Vector to read into
- int numEntries, // IN: Number of vector entries
- uint64 offset, // IN: Offset to start reading
- size_t totalSize, // IN: totalSize (bytes) in entries
- size_t *actual) // OUT: number of bytes read
+FileIO_Preadv(FileIODescriptor *fd, // IN: File descriptor
+ struct iovec const *entries, // IN: Vector to read into
+ int numEntries, // IN: Number of vector entries
+ uint64 offset, // IN: Offset to start reading
+ size_t totalSize, // IN: totalSize (bytes) in entries
+ size_t *actual) // OUT: number of bytes read
{
FileIOResult fret;
@@ -2307,13 +2237,13 @@ FileIO_Preadv(FileIODescriptor *fd, // IN: File descriptor
ASSERT(!(fd->flags & FILEIO_ASYNCHRONOUS));
VERIFY(totalSize < 0x80000000);
-#if defined(__linux__)
+#if defined(__linux__) && !defined(__ANDROID__)
fret = FileIOPreadvInternal(fd, entries, numEntries, offset, totalSize,
actual);
#else
fret = FileIOPreadvCoalesced(fd, entries, numEntries, offset, totalSize,
actual);
-#endif /* defined(__linux__ ) */
+#endif /* defined(__linux__ ) && !defined(__ANDROID__) */
return fret;
}
@@ -2323,7 +2253,7 @@ FileIO_Preadv(FileIODescriptor *fd, // IN: File descriptor
*
* FileIO_Pwritev --
*
- * Implementation of vector pwrite.The function checks for the support
+ * Implementation of vector pwrite. The function checks for the support
* of system call pwritev with the version of glibc and calls the
* optimized system call. If the system call is not supported,
* we fall back to the earlier technique of coalescing the vectors and
@@ -2339,12 +2269,12 @@ FileIO_Preadv(FileIODescriptor *fd, // IN: File descriptor
*/
FileIOResult
-FileIO_Pwritev(FileIODescriptor *fd, // IN: File descriptor
- struct iovec *entries, // IN: Vector to write from
- int numEntries, // IN: Number of vector entries
- uint64 offset, // IN: Offset to start writing
- size_t totalSize, // IN: Total size (bytes) in entries
- size_t *actual) // OUT: number of bytes written
+FileIO_Pwritev(FileIODescriptor *fd, // IN: File descriptor
+ struct iovec const *entries, // IN: Vector to write from
+ int numEntries, // IN: Number of vector entries
+ uint64 offset, // IN: Offset to start writing
+ size_t totalSize, // IN: Total size (bytes) in entries
+ size_t *actual) // OUT: number of bytes written
{
FileIOResult fret;
@@ -2353,18 +2283,18 @@ FileIO_Pwritev(FileIODescriptor *fd, // IN: File descriptor
ASSERT(!(fd->flags & FILEIO_ASYNCHRONOUS));
VERIFY(totalSize < 0x80000000);
-#if defined(__linux__)
+#if defined(__linux__) && !defined(__ANDROID__)
fret = FileIOPwritevInternal(fd, entries, numEntries, offset, totalSize,
actual);
#else
fret = FileIOPwritevCoalesced(fd, entries, numEntries, offset, totalSize,
actual);
-#endif /* defined(__linux__ ) */
+#endif /* defined(__linux__ ) && !defined(__ANDROID__) */
return fret;
}
#endif /* defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||
- defined(sun) */
+ defined(__sun__) */
/*
@@ -2492,9 +2422,9 @@ FileIO_SetAllocSize(const FileIODescriptor *fd, // IN:
*/
FileIOResult
-FileIO_GetAllocSizeByPath(ConstUnicode pathName, // IN:
- uint64 *logicalBytes, // OUT:
- uint64 *allocedBytes) // OUT:
+FileIO_GetAllocSizeByPath(const char *pathName, // IN:
+ uint64 *logicalBytes, // OUT:
+ uint64 *allocedBytes) // OUT:
{
struct stat statBuf;
@@ -2542,8 +2472,8 @@ FileIO_GetAllocSizeByPath(ConstUnicode pathName, // IN:
*/
FileIOResult
-FileIO_Access(ConstUnicode pathName, // IN: Path name. May be NULL.
- int accessMode) // IN: Access modes to be asserted
+FileIO_Access(const char *pathName, // IN: Path name. May be NULL.
+ int accessMode) // IN: Access modes to be asserted
{
int mode = 0;
@@ -2616,10 +2546,10 @@ Bool
FileIO_SupportsFileSize(const FileIODescriptor *fd, // IN:
uint64 requestedSize) // IN:
{
-#if defined(linux)
+#if defined(__linux__)
/*
* Linux makes test on seek(), so we can do simple non-intrusive test.
- * Verified to work on 2.2.x, 2.4.x and 2.6.x, with ext2, ext3, smbfs,
+ * Verified to work on 2.2.x, 2.4.x and 2.6.x, with ext2, ext3, smbfs,
* cifs, nfs and ncpfs. Always got some reasonable value.
*/
Bool supported = FALSE;
@@ -2711,8 +2641,8 @@ FileIO_GetModTime(const FileIODescriptor *fd) // IN:
*/
int
-FileIO_PrivilegedPosixOpen(ConstUnicode pathName, // IN:
- int flags) // IN:
+FileIO_PrivilegedPosixOpen(const char *pathName, // IN:
+ int flags) // IN:
{
int fd;
Bool suDone;
@@ -2840,7 +2770,7 @@ HostSupportsPrealloc(void)
unsigned static const int req[] = { 10, 0, 0, 6 };
unsigned int cur[4], i;
int num;
- size_t len = sizeof(curRel);
+ size_t len = sizeof curRel;
Bool ret = FALSE;
val = Atomic_Read(&supported);
@@ -2879,7 +2809,7 @@ HostSupportsPrealloc(void)
goto exit;
} else if (req[i] < cur[i]) {
ret = TRUE;
- goto exit;
+ goto exit;
}
}
if (num == 5 && type == 'd') {
@@ -2895,7 +2825,7 @@ HostSupportsPrealloc(void)
ret = num != 4;
exit:
- if (!ret && filePosixOptions.initialized &&
+ if (!ret && filePosixOptions.initialized &&
filePosixOptions.aioNumThreads == 1) {
ret = TRUE;
}
@@ -2972,7 +2902,7 @@ FileIO_SupportsPrealloc(const char *pathName, // IN:
#if (defined( __linux__) && !defined(VMX86_SERVER))
{
struct statfs statBuf;
- Unicode fullPath;
+ char *fullPath;
ret = FALSE;
if (!pathName) {
@@ -2988,7 +2918,7 @@ FileIO_SupportsPrealloc(const char *pathName, // IN:
statBuf.f_type == EXT4_SUPER_MAGIC) {
ret = TRUE;
}
- Unicode_Free(fullPath);
+ free(fullPath);
}
#endif
diff --git a/open-vm-tools/lib/file/fileInt.h b/open-vm-tools/lib/file/fileInt.h
index 5faf6ac0..0718e95a 100644
--- a/open-vm-tools/lib/file/fileInt.h
+++ b/open-vm-tools/lib/file/fileInt.h
@@ -119,24 +119,24 @@ Bool FileRetryThisError(DWORD error,
uint32 numCodes,
DWORD *codes);
-int FileAttributesRetry(ConstUnicode pathName,
+int FileAttributesRetry(const char *pathName,
uint32 msecMaxWaitTime,
FileData *fileData);
-int FileDeletionRetry(ConstUnicode pathName,
+int FileDeletionRetry(const char *pathName,
Bool handleLink,
uint32 msecMaxWaitTime);
-int FileCreateDirectoryRetry(ConstUnicode pathName,
+int FileCreateDirectoryRetry(const char *pathName,
int mask,
uint32 msecMaxWaitTime);
-int FileRemoveDirectoryRetry(ConstUnicode pathName,
+int FileRemoveDirectoryRetry(const char *pathName,
uint32 msecMaxWaitTime);
-int FileListDirectoryRetry(ConstUnicode pathName,
+int FileListDirectoryRetry(const char *pathName,
uint32 msecMaxWaitTime,
- Unicode **ids);
+ char ***ids);
#define FileAttributes(a, b) FileAttributesRetry((a), 0, (b))
#define FileDeletion(a, b) FileDeletionRetry((a), (b), 0)
@@ -165,16 +165,16 @@ FileMapErrorToErrno(const char *functionName,
char *FilePosixGetBlockDevice(char const *path);
-int FileAttributes(ConstUnicode pathName,
+int FileAttributes(const char *pathName,
FileData *fileData);
-int FileDeletion(ConstUnicode pathName,
+int FileDeletion(const char *pathName,
Bool handleLink);
-int FileCreateDirectory(ConstUnicode pathName,
+int FileCreateDirectory(const char *pathName,
int mask);
-int FileRemoveDirectory(ConstUnicode pathName);
+int FileRemoveDirectory(const char *pathName);
#define FileListDirectoryRobust(a, b) File_ListDirectory((a), (b))
#define FileAttributesRobust(a, b) FileAttributes((a), (b))
@@ -189,7 +189,7 @@ typedef struct active_lock
struct active_lock *next;
uint32 age;
Bool marked;
- Unicode dirName;
+ char *dirName;
} ActiveLock;
typedef struct lock_values
@@ -198,7 +198,7 @@ typedef struct lock_values
char *executionID;
char *lockType;
char *locationChecksum;
- Unicode memberName;
+ char *memberName;
unsigned int lamportNumber;
Bool exclusivity;
uint32 waitTime;
@@ -221,40 +221,40 @@ const char *FileLockGetMachineID(void);
char *FileLockGetExecutionID(void);
-Bool FileLockMachineIDMatch(char *host,
- char *second);
+Bool FileLockMachineIDMatch(const char *host,
+ const char *second);
-int FileLockMemberValues(ConstUnicode lockDir,
- ConstUnicode fileName,
+int FileLockMemberValues(const char *lockDir,
+ const char *fileName,
char *buffer,
size_t size,
LockValues *memberValues);
-FileLockToken *FileLockIntrinsic(ConstUnicode filePathName,
+FileLockToken *FileLockIntrinsic(const char *filePathName,
Bool exclusivity,
uint32 msecMaxWaitTime,
int *err);
int FileUnlockIntrinsic(FileLockToken *tokenPtr);
-Bool FileLockIsLocked(ConstUnicode filePath,
+Bool FileLockIsLocked(const char *filePath,
int *err);
Bool FileLockValidExecutionID(const char *executionID);
-Bool FileLockValidName(ConstUnicode fileName);
+Bool FileLockValidName(const char *fileName);
void FileLockAppendMessage(MsgList **msgs,
int err);
-Bool FileIsWritableDir(ConstUnicode dirName);
+Bool FileIsWritableDir(const char *dirName);
-UnicodeIndex FileFirstSlashIndex(ConstUnicode pathName,
+UnicodeIndex FileFirstSlashIndex(const char *pathName,
UnicodeIndex startIndex);
FileIOResult
FileIOCreateRetry(FileIODescriptor *fd,
- ConstUnicode pathName,
+ const char *pathName,
int access,
FileIOOpenAction action,
int mode,
@@ -314,7 +314,7 @@ FileIOAligned_Free(void *ptr) // IN:
}
#if defined(__APPLE__)
-int PosixFileOpener(ConstUnicode pathName,
+int PosixFileOpener(const char *pathName,
int flags,
mode_t mode);
#else
diff --git a/open-vm-tools/lib/file/fileLockPosix.c b/open-vm-tools/lib/file/fileLockPosix.c
index c6ff0a4d..71689fa0 100644
--- a/open-vm-tools/lib/file/fileLockPosix.c
+++ b/open-vm-tools/lib/file/fileLockPosix.c
@@ -28,8 +28,8 @@
#include <sys/types.h> /* Needed before sys/vfs.h with glibc 2.0 --hpreg */
#if !defined(__FreeBSD__)
#if defined(__APPLE__)
-#include <sys/param.h>
-#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/mount.h>
#include <sys/times.h>
#include <sys/sysctl.h>
#else
@@ -590,7 +590,7 @@ FileLock_UnlockDevice(const char *deviceName) // IN:
*/
void
-FileLockAppendMessage(MsgList **msgs, // IN/OPT:
+FileLockAppendMessage(MsgList **msgs, // IN/OUT/OPT:
int err) // IN: errno
{
MsgList_Append(msgs, MSGID(fileLock.posix)
@@ -966,8 +966,8 @@ FileLockParseProcessDescriptor(const char *procDescriptor, // IN:
return FALSE;
}
}
-
- return *pid >= 0;
+
+ return *pid >= 0;
}
@@ -1051,14 +1051,14 @@ FileLockValidExecutionID(const char *executionID) // IN:
*---------------------------------------------------------------------------
*/
-static Unicode
-FileLockNormalizePath(ConstUnicode filePath) // IN:
+static char *
+FileLockNormalizePath(const char *filePath) // IN:
{
- Unicode result;
- Unicode fullPath;
+ char *result;
+ char *fullPath;
- Unicode dirName = NULL;
- Unicode fileName = NULL;
+ char *dirName = NULL;
+ char *fileName = NULL;
/*
* If the file to be locked is a symbolic link the lock file belongs next
@@ -1074,9 +1074,9 @@ FileLockNormalizePath(ConstUnicode filePath) // IN:
result = (fullPath == NULL) ? NULL : Unicode_Join(fullPath, DIRSEPS,
fileName, NULL);
- Unicode_Free(fullPath);
- Unicode_Free(dirName);
- Unicode_Free(fileName);
+ free(fullPath);
+ free(dirName);
+ free(fileName);
return result;
}
@@ -1109,14 +1109,14 @@ FileLockNormalizePath(ConstUnicode filePath) // IN:
*/
FileLockToken *
-FileLock_Lock(ConstUnicode filePath, // IN:
+FileLock_Lock(const char *filePath, // IN:
const Bool readOnly, // IN:
const uint32 msecMaxWaitTime, // IN:
int *err, // OUT/OPT: returns errno
- MsgList **msgs) // OUT/OPT: add error message
+ MsgList **msgs) // IN/OUT/OPT: add error message
{
int res = 0;
- Unicode normalizedPath;
+ char *normalizedPath;
FileLockToken *tokenPtr;
ASSERT(filePath);
@@ -1132,7 +1132,7 @@ FileLock_Lock(ConstUnicode filePath, // IN:
tokenPtr = FileLockIntrinsic(normalizedPath, !readOnly, msecMaxWaitTime,
&res);
- Unicode_Free(normalizedPath);
+ free(normalizedPath);
}
if (err != NULL) {
@@ -1171,13 +1171,13 @@ FileLock_Lock(ConstUnicode filePath, // IN:
*/
Bool
-FileLock_IsLocked(ConstUnicode filePath, // IN:
- int *err, // OUT/OPT: returns errno
- MsgList **msgs) // OUT/OPT: add error message
+FileLock_IsLocked(const char *filePath, // IN:
+ int *err, // OUT/OPT: returns errno
+ MsgList **msgs) // IN/OUT/OPT: add error message
{
int res = 0;
Bool isLocked;
- Unicode normalizedPath;
+ char *normalizedPath;
ASSERT(filePath);
@@ -1190,7 +1190,7 @@ FileLock_IsLocked(ConstUnicode filePath, // IN:
} else {
isLocked = FileLockIsLocked(normalizedPath, &res);
- Unicode_Free(normalizedPath);
+ free(normalizedPath);
}
if (err != NULL) {
@@ -1225,7 +1225,7 @@ FileLock_IsLocked(ConstUnicode filePath, // IN:
Bool
FileLock_Unlock(const FileLockToken *lockToken, // IN:
int *err, // OUT/OPT: returns errno
- MsgList **msgs) // OUT/OPT: add error message
+ MsgList **msgs) // IN/OUT/OPT: error messages
{
int res;
diff --git a/open-vm-tools/lib/file/fileLockPrimitive.c b/open-vm-tools/lib/file/fileLockPrimitive.c
index 2673ea92..8e64d79b 100644
--- a/open-vm-tools/lib/file/fileLockPrimitive.c
+++ b/open-vm-tools/lib/file/fileLockPrimitive.c
@@ -88,13 +88,13 @@ struct FileLockToken
{
uint32 signature;
Bool portable;
- Unicode pathName;
+ char *pathName;
union {
struct {
FileIODescriptor lockFd;
} mandatory;
struct {
- Unicode lockFilePath; // &implicitReadToken for implicit read locks
+ char *lockFilePath; // &implicitReadToken for implicit read locks
} portable;
} u;
};
@@ -175,11 +175,11 @@ FileLockSleeper(LockValues *myValues, // IN/OUT:
*/
static int
-FileLockRemoveLockingFile(ConstUnicode lockDir, // IN:
- ConstUnicode fileName) // IN:
+FileLockRemoveLockingFile(const char *lockDir, // IN:
+ const char *fileName) // IN:
{
int err;
- Unicode path;
+ char *path;
ASSERT(lockDir);
ASSERT(fileName);
@@ -194,11 +194,11 @@ FileLockRemoveLockingFile(ConstUnicode lockDir, // IN:
err = 0;
} else {
Warning(LGPFX" %s of '%s' failed: %s\n", __FUNCTION__,
- UTF8(path), strerror(err));
+ path, strerror(err));
}
}
- Unicode_Free(path);
+ free(path);
return err;
}
@@ -290,15 +290,15 @@ FileLockParseArgs(char *argv[], // IN:
#define FL_MAX_ARGS 16
int
-FileLockMemberValues(ConstUnicode lockDir, // IN:
- ConstUnicode fileName, // IN:
+FileLockMemberValues(const char *lockDir, // IN:
+ const char *fileName, // IN:
char *buffer, // OUT:
size_t requiredSize, // IN:
LockValues *memberValues) // OUT:
{
size_t len;
int access;
- Unicode path;
+ char *path;
FileData fileData;
FileIOResult result;
FileIODescriptor desc;
@@ -314,7 +314,7 @@ FileLockMemberValues(ConstUnicode lockDir, // IN:
(void *) &memberValues->locationChecksum
}
};
-
+
ASSERT(lockDir);
ASSERT(fileName);
@@ -343,7 +343,7 @@ FileLockMemberValues(ConstUnicode lockDir, // IN:
if (err != ENOENT) {
Warning(LGPFX" %s open failure on '%s': %s\n", __FUNCTION__,
- UTF8(path), strerror(err));
+ path, strerror(err));
}
goto bail;
@@ -362,7 +362,7 @@ FileLockMemberValues(ConstUnicode lockDir, // IN:
if (err != ENOENT) {
Warning(LGPFX" %s file size failure on '%s': %s\n", __FUNCTION__,
- UTF8(path), strerror(err));
+ path, strerror(err));
}
FileIO_Close(&desc);
@@ -373,7 +373,7 @@ FileLockMemberValues(ConstUnicode lockDir, // IN:
/* Complain if the lock file is not the proper size */
if (fileData.fileSize != requiredSize) {
Warning(LGPFX" %s file '%s': size %"FMT64"u, required size %"FMTSZ"d\n",
- __FUNCTION__, UTF8(path), fileData.fileSize, requiredSize);
+ __FUNCTION__, path, fileData.fileSize, requiredSize);
FileIO_Close(&desc);
@@ -389,14 +389,14 @@ FileLockMemberValues(ConstUnicode lockDir, // IN:
err = FileMapErrorToErrno(__FUNCTION__, Err_Errno());
Warning(LGPFX" %s read failure on '%s': %s\n",
- __FUNCTION__, UTF8(path), strerror(err));
+ __FUNCTION__, path, strerror(err));
goto bail;
}
if (len != requiredSize) {
Warning(LGPFX" %s read length issue on '%s': %"FMTSZ"d and %"FMTSZ"d\n",
- __FUNCTION__, UTF8(path), len, requiredSize);
+ __FUNCTION__, path, len, requiredSize);
err = EIO;
goto bail;
@@ -482,21 +482,21 @@ fixedUp:
memberValues->lockType = argv[3];
memberValues->memberName = Unicode_Duplicate(fileName);
- Unicode_Free(path);
+ free(path);
return 0;
corrupt:
Warning(LGPFX" %s removing problematic lock file '%s'\n", __FUNCTION__,
- UTF8(path));
+ path);
if (argc) {
uint32 i;
- Log(LGPFX" %s '%s' contents are:\n", __FUNCTION__, UTF8(fileName));
+ Log(LGPFX" %s '%s' contents are:\n", __FUNCTION__, fileName);
for (i = 0; i < argc; i++) {
- Log(LGPFX" %s %s argv[%u]: '%s'\n", __FUNCTION__, UTF8(fileName),
+ Log(LGPFX" %s %s argv[%u]: '%s'\n", __FUNCTION__, fileName,
i, argv[i]);
}
}
@@ -509,7 +509,7 @@ corrupt:
}
bail:
- Unicode_Free(path);
+ free(path);
return err;
}
@@ -533,7 +533,7 @@ bail:
*/
Bool
-FileLockValidName(ConstUnicode fileName) // IN:
+FileLockValidName(const char *fileName) // IN:
{
uint32 i;
@@ -576,14 +576,14 @@ FileLockValidName(ConstUnicode fileName) // IN:
*/
static int
-FileLockActivateList(ConstUnicode dirName, // IN:
- LockValues *myValues) // IN:
+FileLockActivateList(const char *dirName, // IN:
+ LockValues *myValues) // IN:
{
ActiveLock *ptr;
ASSERT(dirName);
- ASSERT(Unicode_StartsWith(dirName, "D"));
+ ASSERT(*dirName == 'D');
/* Search the list for a matching entry */
for (ptr = myValues->lockList; ptr != NULL; ptr = ptr->next) {
@@ -627,14 +627,14 @@ FileLockActivateList(ConstUnicode dirName, // IN:
*/
static char *
-FileLockLocationChecksum(ConstUnicode path) // IN:
+FileLockLocationChecksum(const char *path) // IN:
{
int c;
uint32 hash = 5381;
#if defined(_WIN32)
char *p;
- Unicode value = Unicode_Duplicate(path);
+ char *value = Unicode_Duplicate(path);
/* Don't get fooled by mixed case; "normalize" */
Str_ToLower(value);
@@ -649,7 +649,7 @@ FileLockLocationChecksum(ConstUnicode path) // IN:
}
#if defined(_WIN32)
- Unicode_Free(value);
+ free(value);
#endif
return Str_SafeAsprintf(NULL, "%u", hash);
@@ -675,10 +675,10 @@ FileLockLocationChecksum(ConstUnicode path) // IN:
*/
static int
-FileLockScanDirectory(ConstUnicode lockDir, // IN:
+FileLockScanDirectory(const char *lockDir, // IN:
int (*func)( // IN:
- ConstUnicode lockDir,
- ConstUnicode fileName,
+ const char *lockDir,
+ const char *fileName,
LockValues *memberValues,
LockValues *myValues
),
@@ -689,7 +689,7 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
int err;
int numEntries;
- Unicode *fileList = NULL;
+ char **fileList = NULL;
char *myExecutionID = NULL;
char *locationChecksum = NULL;
@@ -699,7 +699,7 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
if (numEntries == -1) {
Log(LGPFX" %s: Could not read the directory '%s': %d\n",
- __FUNCTION__, UTF8(lockDir), Err_Errno());
+ __FUNCTION__, lockDir, Err_Errno());
return EDOM; // out of my domain
}
@@ -709,14 +709,14 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
/* Remove any non-locking files */
if (!FileLockValidName(fileList[i])) {
Log(LGPFX" %s discarding %s from %s'; invalid file name.\n",
- __FUNCTION__, UTF8(fileList[i]), UTF8(lockDir));
+ __FUNCTION__, fileList[i], lockDir);
err = FileLockRemoveLockingFile(lockDir, fileList[i]);
if (err != 0) {
goto bail;
}
- Unicode_Free(fileList[i]);
+ free(fileList[i]);
fileList[i] = NULL;
continue;
@@ -729,7 +729,7 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
* this will cleaned-up.
*/
- if (Unicode_StartsWith(fileList[i], "D")) {
+ if (*fileList[i] == 'D') {
if (cleanUp) {
err = FileLockActivateList(fileList[i], myValues);
if (err != 0) {
@@ -737,7 +737,7 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
}
}
- Unicode_Free(fileList[i]);
+ free(fileList[i]);
fileList[i] = NULL;
}
}
@@ -757,7 +757,7 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
char buffer[FILELOCK_DATA_SIZE];
if ((fileList[i] == NULL) ||
- (Unicode_StartsWith(fileList[i], "E"))) {
+ (*fileList[i] == 'E')) {
continue;
}
@@ -785,7 +785,7 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
/* Remove any stale locking files */
if (FileLockMachineIDMatch(myValues->machineID,
memberValues.machineID)) {
- Unicode dispose = NULL;
+ char *dispose = NULL;
if (FileLockValidExecutionID(memberValues.executionID)) {
/* If it's mine it better still be where I put it! */
@@ -802,10 +802,10 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
if (dispose) {
Log(LGPFX" %s discarding %s from %s': %s\n",
- __FUNCTION__, UTF8(fileList[i]), UTF8(lockDir), dispose);
+ __FUNCTION__, fileList[i], lockDir, dispose);
- Unicode_Free(dispose);
- Unicode_Free(memberValues.memberName);
+ free(dispose);
+ free(memberValues.memberName);
err = FileLockRemoveLockingFile(lockDir, fileList[i]);
if (err != 0) {
@@ -823,7 +823,7 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
err = (*func)(lockDir, fileList[i], ptr, myValues);
if (ptr == &memberValues) {
- Unicode_Free(memberValues.memberName);
+ free(memberValues.memberName);
}
if (err != 0) {
@@ -833,11 +833,8 @@ FileLockScanDirectory(ConstUnicode lockDir, // IN:
bail:
- for (i = 0; i < numEntries; i++) {
- Unicode_Free(fileList[i]);
- }
+ Util_FreeStringList(fileList, numEntries);
- free(fileList);
free(locationChecksum);
free(myExecutionID);
@@ -865,10 +862,10 @@ bail:
*/
static int
-FileLockScanner(ConstUnicode lockDir, // IN:
+FileLockScanner(const char *lockDir, // IN:
int (*func)( // IN:
- ConstUnicode lockDir,
- ConstUnicode fileName,
+ const char *lockDir,
+ const char *fileName,
LockValues *memberValues,
LockValues *myValues
),
@@ -903,14 +900,14 @@ FileLockScanner(ConstUnicode lockDir, // IN:
if (ptr->marked) {
if (ptr->age > FILELOCK_PROGRESS_DEARTH) {
- Unicode temp;
- Unicode path;
+ char *temp;
+ char *path;
UnicodeIndex index;
- ASSERT(Unicode_StartsWith(ptr->dirName, "D"));
+ ASSERT(*ptr->dirName == 'D');
Log(LGPFX" %s discarding %s data from '%s'.\n",
- __FUNCTION__, UTF8(ptr->dirName), UTF8(lockDir));
+ __FUNCTION__, ptr->dirName, lockDir);
path = Unicode_Join(lockDir, DIRSEPS, ptr->dirName, NULL);
@@ -919,15 +916,15 @@ FileLockScanner(ConstUnicode lockDir, // IN:
temp = Unicode_Replace(path, index, 1, "M");
FileDeletionRobust(temp, FALSE);
- Unicode_Free(temp);
+ free(temp);
temp = Unicode_Replace(path, index, 1, "E");
FileDeletionRobust(temp, FALSE);
- Unicode_Free(temp);
+ free(temp);
FileRemoveDirectoryRobust(path);
- Unicode_Free(path);
+ free(path);
remove = TRUE;
} else {
@@ -961,7 +958,7 @@ FileLockScanner(ConstUnicode lockDir, // IN:
ptr = myValues->lockList;
myValues->lockList = ptr->next;
- Unicode_Free(ptr->dirName);
+ free(ptr->dirName);
free(ptr);
}
@@ -994,7 +991,7 @@ FileUnlockIntrinsic(FileLockToken *tokenPtr) // IN:
ASSERT(tokenPtr && (tokenPtr->signature == FILELOCK_TOKEN_SIGNATURE));
- LOG(1, ("Requesting unlock on %s\n", UTF8(tokenPtr->pathName)));
+ LOG(1, ("Requesting unlock on %s\n", tokenPtr->pathName));
if (tokenPtr->portable) {
@@ -1005,7 +1002,7 @@ FileUnlockIntrinsic(FileLockToken *tokenPtr) // IN:
*/
if (tokenPtr->u.portable.lockFilePath != &implicitReadToken) {
- Unicode lockDir;
+ char *lockDir;
/* The lock directory path */
lockDir = Unicode_Append(tokenPtr->pathName, FILELOCK_SUFFIX);
@@ -1021,20 +1018,20 @@ FileUnlockIntrinsic(FileLockToken *tokenPtr) // IN:
if (err && vmx86_debug) {
Log(LGPFX" %s failed for '%s': %s\n", __FUNCTION__,
- UTF8(tokenPtr->u.portable.lockFilePath), strerror(err));
+ tokenPtr->u.portable.lockFilePath, strerror(err));
}
- Unicode_Free(lockDir);
- Unicode_Free(tokenPtr->u.portable.lockFilePath);
+ free(lockDir);
+ free(tokenPtr->u.portable.lockFilePath);
}
tokenPtr->u.portable.lockFilePath = NULL; // Just in case...
} else {
ASSERT(FileIO_IsValid(&tokenPtr->u.mandatory.lockFd));
- if (FileIO_CloseAndUnlink(&tokenPtr->u.mandatory.lockFd)) {
+ if (!FileIO_IsSuccess(FileIO_CloseAndUnlink(&tokenPtr->u.mandatory.lockFd))) {
/*
* Should succeed, but there is an unavoidable race:
- * close() must preceed unlink(), but another thread could touch
+ * close() must precede unlink(), but another thread could touch
* the file between close() and unlink(). We only worry about other
* FileLock-like manipulations; the advisory lock file should not
* experience any name collisions. Treat races as success.
@@ -1045,18 +1042,18 @@ FileUnlockIntrinsic(FileLockToken *tokenPtr) // IN:
if (Err_Errno() == EBUSY || Err_Errno() == ENOENT) {
LOG(0, ("Tolerating %s on unlink of advisory lock at %s\n",
Err_Errno() == EBUSY ? "EBUSY" : "ENOENT",
- UTF8(tokenPtr->pathName)));
+ tokenPtr->pathName));
} else {
err = Err_Errno();
if (vmx86_debug) {
Log(LGPFX" %s failed for advisory lock '%s': %s\n", __FUNCTION__,
- UTF8(tokenPtr->pathName), strerror(err));
+ tokenPtr->pathName, strerror(err));
}
}
}
}
- Unicode_Free(tokenPtr->pathName);
+ free(tokenPtr->pathName);
tokenPtr->signature = 0; // Just in case...
tokenPtr->pathName = NULL; // Just in case...
free(tokenPtr);
@@ -1084,8 +1081,8 @@ FileUnlockIntrinsic(FileLockToken *tokenPtr) // IN:
*/
static int
-FileLockWaitForPossession(ConstUnicode lockDir, // IN:
- ConstUnicode fileName, // IN:
+FileLockWaitForPossession(const char *lockDir, // IN:
+ const char *fileName, // IN:
LockValues *memberValues, // IN:
LockValues *myValues) // IN:
{
@@ -1101,9 +1098,9 @@ FileLockWaitForPossession(ConstUnicode lockDir, // IN:
myValues->memberName) < 0))) &&
((strcmp(memberValues->lockType, LOCK_EXCLUSIVE) == 0) ||
(strcmp(myValues->lockType, LOCK_EXCLUSIVE) == 0))) {
- Unicode path;
+ char *path;
uint32 loopCount;
- Bool thisMachine;
+ Bool thisMachine;
thisMachine = FileLockMachineIDMatch(myValues->machineID,
memberValues->machineID);
@@ -1129,7 +1126,7 @@ FileLockWaitForPossession(ConstUnicode lockDir, // IN:
!FileLockValidExecutionID(memberValues->executionID)) {
/* Invalid Execution ID; remove the member file */
Warning(LGPFX" %s discarding file '%s'; invalid executionID.\n",
- __FUNCTION__, UTF8(path));
+ __FUNCTION__, path);
err = FileLockRemoveLockingFile(lockDir, fileName);
break;
@@ -1145,14 +1142,14 @@ FileLockWaitForPossession(ConstUnicode lockDir, // IN:
(err == EAGAIN)) {
if (thisMachine) {
Log(LGPFX" %s timeout on '%s' due to a local process '%s'\n",
- __FUNCTION__, UTF8(path), memberValues->executionID);
+ __FUNCTION__, path, memberValues->executionID);
} else {
Log(LGPFX" %s timeout on '%s' due to another machine '%s'\n",
- __FUNCTION__, UTF8(path), memberValues->machineID);
+ __FUNCTION__, path, memberValues->machineID);
}
}
- Unicode_Free(path);
+ free(path);
}
return err;
@@ -1177,8 +1174,8 @@ FileLockWaitForPossession(ConstUnicode lockDir, // IN:
*/
static int
-FileLockNumberScan(ConstUnicode lockDir, // IN:
- ConstUnicode fileName, // IN:
+FileLockNumberScan(const char *lockDir, // IN:
+ const char *fileName, // IN:
LockValues *memberValues, // IN:
LockValues *myValues) // IN/OUT:
{
@@ -1211,7 +1208,7 @@ FileLockNumberScan(ConstUnicode lockDir, // IN:
*/
static int
-FileLockMakeDirectory(ConstUnicode pathName) // IN:
+FileLockMakeDirectory(const char *pathName) // IN:
{
int err;
@@ -1259,11 +1256,11 @@ FileLockMakeDirectory(ConstUnicode pathName) // IN:
*/
static int
-FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
- Unicode *entryDirectory, // OUT:
- Unicode *entryFilePath, // OUT:
- Unicode *memberFilePath, // OUT:
- Unicode *memberName) // OUT:
+FileLockCreateEntryDirectory(const char *lockDir, // IN:
+ char **entryDirectory, // OUT:
+ char **entryFilePath, // OUT:
+ char **memberFilePath, // OUT:
+ char **memberName) // OUT:
{
int err = 0;
uint32 randomNumber = 0;
@@ -1278,7 +1275,7 @@ FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
/* Fun at the races */
while (TRUE) {
- Unicode temp;
+ char *temp;
FileData fileData;
err = FileAttributesRobust(lockDir, &fileData);
@@ -1293,7 +1290,7 @@ FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
*/
Log(LGPFX" %s: '%s' exists; an old style lock file?\n",
- __FUNCTION__, UTF8(lockDir));
+ __FUNCTION__, lockDir);
err = EBUSY;
break;
@@ -1303,7 +1300,7 @@ FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
/* Not a directory; attempt to remove the debris */
if (FileDeletionRobust(lockDir, FALSE) != 0) {
Warning(LGPFX" %s: '%s' exists and is not a directory.\n",
- __FUNCTION__, UTF8(lockDir));
+ __FUNCTION__, lockDir);
err = ENOTDIR;
break;
@@ -1318,13 +1315,13 @@ FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
if ((err != 0) && (err != EEXIST)) {
Warning(LGPFX" %s creation failure on '%s': %s\n",
- __FUNCTION__, UTF8(lockDir), strerror(err));
+ __FUNCTION__, lockDir, strerror(err));
break;
}
} else {
Warning(LGPFX" %s stat failure on '%s': %s\n",
- __FUNCTION__, UTF8(lockDir), strerror(err));
+ __FUNCTION__, lockDir, strerror(err));
break;
}
@@ -1337,11 +1334,11 @@ FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
temp = Unicode_Format("D%05u%s", randomNumber, FILELOCK_SUFFIX);
*entryDirectory = Unicode_Join(lockDir, DIRSEPS, temp, NULL);
- Unicode_Free(temp);
+ free(temp);
temp = Unicode_Format("E%05u%s", randomNumber, FILELOCK_SUFFIX);
*entryFilePath = Unicode_Join(lockDir, DIRSEPS, temp, NULL);
- Unicode_Free(temp);
+ free(temp);
*memberFilePath = Unicode_Join(lockDir, DIRSEPS, *memberName, NULL);
@@ -1368,7 +1365,7 @@ FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
if (vmx86_debug) {
Log(LGPFX" %s stat failure on '%s': %s\n",
- __FUNCTION__, UTF8(*memberFilePath), strerror(err));
+ __FUNCTION__, *memberFilePath, strerror(err));
}
}
@@ -1377,16 +1374,16 @@ FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
if ((err != EEXIST) && // Another process/thread created it...
(err != ENOENT)) { // lockDir is gone...
Warning(LGPFX" %s creation failure on '%s': %s\n",
- __FUNCTION__, UTF8(*entryDirectory), strerror(err));
+ __FUNCTION__, *entryDirectory, strerror(err));
break;
}
}
- Unicode_Free(*entryDirectory);
- Unicode_Free(*entryFilePath);
- Unicode_Free(*memberFilePath);
- Unicode_Free(*memberName);
+ free(*entryDirectory);
+ free(*entryFilePath);
+ free(*memberFilePath);
+ free(*memberName);
*entryDirectory = NULL;
*entryFilePath = NULL;
@@ -1395,10 +1392,10 @@ FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
}
if (err != 0) {
- Unicode_Free(*entryDirectory);
- Unicode_Free(*entryFilePath);
- Unicode_Free(*memberFilePath);
- Unicode_Free(*memberName);
+ free(*entryDirectory);
+ free(*entryFilePath);
+ free(*memberFilePath);
+ free(*memberName);
*entryDirectory = NULL;
*entryFilePath = NULL;
@@ -1430,8 +1427,8 @@ FileLockCreateEntryDirectory(ConstUnicode lockDir, // IN:
static int
FileLockCreateMemberFile(FileIODescriptor *desc, // IN:
const LockValues *myValues, // IN:
- ConstUnicode entryFilePath, // IN:
- ConstUnicode memberFilePath) // IN:
+ const char *entryFilePath, // IN:
+ const char *memberFilePath) // IN:
{
int cnt;
int pid;
@@ -1483,25 +1480,25 @@ FileLockCreateMemberFile(FileIODescriptor *desc, // IN:
err = FileMapErrorToErrno(__FUNCTION__, Err_Errno());
Warning(LGPFX" %s write of '%s' failed: %s\n", __FUNCTION__,
- UTF8(entryFilePath), strerror(err));
+ entryFilePath, strerror(err));
FileIO_Close(desc);
return err;
}
- if (FileIO_Close(desc)) {
+ if (!FileIO_IsSuccess(FileIO_Close(desc))) {
err = FileMapErrorToErrno(__FUNCTION__, Err_Errno());
Warning(LGPFX" %s close of '%s' failed: %s\n", __FUNCTION__,
- UTF8(entryFilePath), strerror(err));
+ entryFilePath, strerror(err));
return err;
}
if (len != sizeof buffer) {
Warning(LGPFX" %s write length issue on '%s': %"FMTSZ"d and %"FMTSZ"d\n",
- __FUNCTION__, UTF8(entryFilePath), len, sizeof buffer);
+ __FUNCTION__, entryFilePath, len, sizeof buffer);
return EIO;
}
@@ -1510,16 +1507,16 @@ FileLockCreateMemberFile(FileIODescriptor *desc, // IN:
if (err != 0) {
Warning(LGPFX" %s FileRename of '%s' to '%s' failed: %s\n",
- __FUNCTION__, UTF8(entryFilePath), UTF8(memberFilePath),
+ __FUNCTION__, entryFilePath, memberFilePath,
strerror(err));
if (vmx86_debug) {
Log(LGPFX" %s FileLockFileType() of '%s': %s\n",
- __FUNCTION__, UTF8(entryFilePath),
+ __FUNCTION__, entryFilePath,
strerror(FileAttributesRobust(entryFilePath, NULL)));
Log(LGPFX" %s FileLockFileType() of '%s': %s\n",
- __FUNCTION__, UTF8(memberFilePath),
+ __FUNCTION__, memberFilePath,
strerror(FileAttributesRobust(memberFilePath, NULL)));
}
@@ -1561,15 +1558,15 @@ FileLockCreateMemberFile(FileIODescriptor *desc, // IN:
*/
static FileLockToken *
-FileLockIntrinsicMandatory(ConstUnicode pathName, // IN:
- ConstUnicode lockFile, // IN:
- LockValues *myValues, // IN/OUT:
- int *err) // OUT:
+FileLockIntrinsicMandatory(const char *pathName, // IN:
+ const char *lockFile, // IN:
+ LockValues *myValues, // IN/OUT:
+ int *err) // OUT:
{
int access;
int loopCount = 0;
FileIOResult result;
- FileLockToken *tokenPtr = Util_SafeMalloc(sizeof(FileLockToken));
+ FileLockToken *tokenPtr = Util_SafeMalloc(sizeof *tokenPtr);
tokenPtr->signature = FILELOCK_TOKEN_SIGNATURE;
tokenPtr->portable = FALSE;
@@ -1597,7 +1594,7 @@ FileLockIntrinsicMandatory(ConstUnicode pathName, // IN:
return tokenPtr;
} else {
*err = FileMapErrorToErrno(__FUNCTION__, Err_Errno());
- Unicode_Free(tokenPtr->pathName);
+ free(tokenPtr->pathName);
ASSERT(!FileIO_IsValid(&tokenPtr->u.mandatory.lockFd));
free(tokenPtr);
@@ -1614,8 +1611,8 @@ FileLockIntrinsicMandatory(ConstUnicode pathName, // IN:
* Obtain a lock on a file; shared or exclusive access.
*
* This implementation uses a HIGHLY portable directory-namespace +
- * Lamport bakery scheme that works on all filesystems that provide atomicity
- * of the directory namespace. (That is, all known filesystems.)
+ * Lamport bakery scheme that works on all filesystems that provide
+ * atomicity of the directory namespace (That is, all known filesystems).
* The various files involved are hidden within a "pathName.lck/"
* subdirectory.
*
@@ -1637,19 +1634,19 @@ FileLockIntrinsicMandatory(ConstUnicode pathName, // IN:
*/
static FileLockToken *
-FileLockIntrinsicPortable(ConstUnicode pathName, // IN:
- ConstUnicode lockDir, // IN:
- LockValues *myValues, // IN/OUT:
- int *err) // OUT:
+FileLockIntrinsicPortable(const char *pathName, // IN:
+ const char *lockDir, // IN:
+ LockValues *myValues, // IN/OUT:
+ int *err) // OUT:
{
int access;
FileIOResult result;
FileIODescriptor desc;
FileLockToken *tokenPtr;
- Unicode entryFilePath = NULL;
- Unicode memberFilePath = NULL;
- Unicode entryDirectory = NULL;
+ char *entryFilePath = NULL;
+ char *memberFilePath = NULL;
+ char *entryDirectory = NULL;
ASSERT(pathName);
ASSERT(err);
@@ -1678,7 +1675,7 @@ FileLockIntrinsicPortable(ConstUnicode pathName, // IN:
*/
Warning(LGPFX" %s implicit %s lock succeeded on '%s'.\n",
- __FUNCTION__, LOCK_SHARED, UTF8(pathName));
+ __FUNCTION__, LOCK_SHARED, pathName);
*err = 0;
memberFilePath = &implicitReadToken;
@@ -1769,18 +1766,18 @@ FileLockIntrinsicPortable(ConstUnicode pathName, // IN:
bail:
- Unicode_Free(entryDirectory);
- Unicode_Free(entryFilePath);
+ free(entryDirectory);
+ free(entryFilePath);
if (*err == 0) {
- tokenPtr = Util_SafeMalloc(sizeof(FileLockToken));
+ tokenPtr = Util_SafeMalloc(sizeof *tokenPtr);
tokenPtr->signature = FILELOCK_TOKEN_SIGNATURE;
tokenPtr->portable = TRUE;
tokenPtr->pathName = Unicode_Duplicate(pathName);
tokenPtr->u.portable.lockFilePath = memberFilePath;
} else {
- Unicode_Free(memberFilePath);
+ free(memberFilePath);
tokenPtr = NULL;
if (*err == EAGAIN) {
@@ -1829,12 +1826,12 @@ bail:
*/
FileLockToken *
-FileLockIntrinsic(ConstUnicode pathName, // IN:
+FileLockIntrinsic(const char *pathName, // IN:
Bool exclusivity, // IN:
uint32 msecMaxWaitTime, // IN:
int *err) // OUT:
{
- Unicode lockBase;
+ char *lockBase;
LockValues myValues = { 0 };
FileLockToken *tokenPtr;
@@ -1848,7 +1845,7 @@ FileLockIntrinsic(ConstUnicode pathName, // IN:
if (File_SupportsMandatoryLock(pathName)) {
LOG(1, ("Requesting %s lock on %s (mandatory, %u).\n",
- myValues.lockType, UTF8(pathName), myValues.msecMaxWaitTime));
+ myValues.lockType, pathName, myValues.msecMaxWaitTime));
tokenPtr = FileLockIntrinsicMandatory(pathName, lockBase, &myValues, err);
} else {
@@ -1859,17 +1856,17 @@ FileLockIntrinsic(ConstUnicode pathName, // IN:
myValues.memberName = NULL;
LOG(1, ("Requesting %s lock on %s (%s, %s, %u).\n",
- myValues.lockType, UTF8(pathName), myValues.machineID,
+ myValues.lockType, pathName, myValues.machineID,
myValues.executionID, myValues.msecMaxWaitTime));
tokenPtr = FileLockIntrinsicPortable(pathName, lockBase, &myValues, err);
- Unicode_Free(myValues.memberName);
+ free(myValues.memberName);
free(myValues.locationChecksum);
free(myValues.executionID);
}
- Unicode_Free(lockBase);
+ free(lockBase);
return tokenPtr;
}
@@ -1897,8 +1894,8 @@ FileLockIntrinsic(ConstUnicode pathName, // IN:
*/
static Bool
-FileLockIsLockedMandatory(ConstUnicode lockFile, // IN:
- int *err) // OUT/OPT:
+FileLockIsLockedMandatory(const char *lockFile, // IN:
+ int *err) // OUT/OPT:
{
int access;
FileIOResult result;
@@ -1919,7 +1916,7 @@ FileLockIsLockedMandatory(ConstUnicode lockFile, // IN:
if (FileIO_IsSuccess(result)) {
Bool ret;
- ret = FileIO_Close(&desc);
+ ret = !FileIO_IsSuccess(FileIO_Close(&desc));
ASSERT(!ret);
return FALSE;
@@ -1961,13 +1958,13 @@ FileLockIsLockedMandatory(ConstUnicode lockFile, // IN:
*/
static Bool
-FileLockIsLockedPortable(ConstUnicode lockDir, // IN:
- int *err) // OUT/OPT:
+FileLockIsLockedPortable(const char *lockDir, // IN:
+ int *err) // OUT/OPT:
{
uint32 i;
int numEntries;
Bool isLocked = FALSE;
- Unicode *fileList = NULL;
+ char **fileList = NULL;
numEntries = FileListDirectoryRobust(lockDir, &fileList);
@@ -1985,17 +1982,13 @@ FileLockIsLockedPortable(ConstUnicode lockDir, // IN:
}
for (i = 0; i < numEntries; i++) {
- if (Unicode_StartsWith(fileList[i], "M")) {
+ if (*fileList[i] == 'M') {
isLocked = TRUE;
break;
}
}
- for (i = 0; i < numEntries; i++) {
- Unicode_Free(fileList[i]);
- }
-
- free(fileList);
+ Util_FreeStringList(fileList, numEntries);
return isLocked;
}
@@ -2019,11 +2012,11 @@ FileLockIsLockedPortable(ConstUnicode lockDir, // IN:
*/
Bool
-FileLockIsLocked(ConstUnicode pathName, // IN:
- int *err) // OUT/OPT:
+FileLockIsLocked(const char *pathName, // IN:
+ int *err) // OUT/OPT:
{
Bool isLocked;
- Unicode lockBase;
+ char *lockBase;
ASSERT(pathName);
@@ -2035,7 +2028,7 @@ FileLockIsLocked(ConstUnicode pathName, // IN:
isLocked = FileLockIsLockedPortable(lockBase, err);
}
- Unicode_Free(lockBase);
+ free(lockBase);
return isLocked;
}
@@ -2059,7 +2052,7 @@ FileLockIsLocked(ConstUnicode pathName, // IN:
*----------------------------------------------------------------------
*/
-Unicode
+char *
FileLock_TokenPathName(const FileLockToken *lockToken) // IN:
{
ASSERT(lockToken && (lockToken->signature == FILELOCK_TOKEN_SIGNATURE));
diff --git a/open-vm-tools/lib/file/filePosix.c b/open-vm-tools/lib/file/filePosix.c
index 718f7b20..c88e6746 100644
--- a/open-vm-tools/lib/file/filePosix.c
+++ b/open-vm-tools/lib/file/filePosix.c
@@ -91,31 +91,15 @@ static char *FilePosixNearestExistingAncestor(char const *path);
#include "fs_user.h"
#endif
-
-/*
- * XXX
- * FTS is not available on all posix platforms that we care about.
- * We depend on FTS for a simple pre-order file traversal. For the Windows
- * implementation we need to write our own traversal code anyway. When that
- * happens the prosix version should be updated to use the generic code.
- */
-
-#if defined(__USE_FILE_OFFSET64) || defined(sun) || defined(__ANDROID__)
-# define CAN_USE_FTS 0
-#else
-# define CAN_USE_FTS 1
-#endif
-
-#if CAN_USE_FTS
-# include <fts.h>
-
struct WalkDirContextImpl {
- FTS *fts;
+ int cnt;
+ int iter;
+ char **files;
};
-#endif
/* A string for NFS on ESX file system type */
+#define FS_NFS_PREFIX_LEN 3
#define FS_NFS_ON_ESX "NFS"
/* A string for VMFS on ESX file system type */
#define FS_VMFS_ON_ESX "VMFS"
@@ -151,7 +135,7 @@ struct WalkDirContextImpl {
*/
int
-FileRemoveDirectory(ConstUnicode pathName) // IN:
+FileRemoveDirectory(const char *pathName) // IN:
{
return (Posix_Rmdir(pathName) == -1) ? errno : 0;
}
@@ -175,16 +159,16 @@ FileRemoveDirectory(ConstUnicode pathName) // IN:
*/
int
-File_Rename(ConstUnicode oldName, // IN:
- ConstUnicode newName) // IN:
+File_Rename(const char *oldName, // IN:
+ const char *newName) // IN:
{
return (Posix_Rename(oldName, newName) == -1) ? errno : 0;
}
int
-File_RenameRetry(ConstUnicode oldFile, // IN:
- ConstUnicode newFile, // IN:
+File_RenameRetry(const char *oldFile, // IN:
+ const char *newFile, // IN:
uint32 msecMaxWaitTime) // IN: Unused.
{
return File_Rename(oldFile, newFile);
@@ -209,7 +193,7 @@ File_RenameRetry(ConstUnicode oldFile, // IN:
*/
int
-FileDeletion(ConstUnicode pathName, // IN:
+FileDeletion(const char *pathName, // IN:
const Bool handleLink) // IN:
{
int err;
@@ -221,7 +205,7 @@ FileDeletion(ConstUnicode pathName, // IN:
}
if (handleLink) {
- Unicode linkPath = Posix_ReadLink(pathName);
+ char *linkPath = Posix_ReadLink(pathName);
if (linkPath == NULL) {
/* If there is no link involved, continue */
@@ -233,7 +217,7 @@ FileDeletion(ConstUnicode pathName, // IN:
} else {
err = (Posix_Unlink(linkPath) == -1) ? errno : 0;
- Unicode_Free(linkPath);
+ free(linkPath);
/* Ignore a file that has already disappeared */
if (err != ENOENT) {
@@ -267,7 +251,7 @@ bail:
*/
int
-File_UnlinkDelayed(ConstUnicode pathName) // IN:
+File_UnlinkDelayed(const char *pathName) // IN:
{
return (FileDeletion(pathName, TRUE) == 0) ? 0 : -1;
}
@@ -291,8 +275,8 @@ File_UnlinkDelayed(ConstUnicode pathName) // IN:
*/
int
-FileAttributes(ConstUnicode pathName, // IN:
- FileData *fileData) // OUT:
+FileAttributes(const char *pathName, // IN:
+ FileData *fileData) // OUT:
{
int err;
struct stat statbuf;
@@ -378,7 +362,7 @@ FileAttributes(ConstUnicode pathName, // IN:
#if !defined(__FreeBSD__) && !defined(sun)
Bool
-File_IsRemote(ConstUnicode pathName) // IN: Path name
+File_IsRemote(const char *pathName) // IN: Path name
{
if (HostType_OSIsVMK()) {
/*
@@ -391,7 +375,7 @@ File_IsRemote(ConstUnicode pathName) // IN: Path name
struct statfs sfbuf;
if (Posix_Statfs(pathName, &sfbuf) == -1) {
- Log(LGPFX" %s: statfs(%s) failed: %s\n", __func__, UTF8(pathName),
+ Log(LGPFX" %s: statfs(%s) failed: %s\n", __func__, pathName,
Err_Errno2String(errno));
return TRUE;
@@ -435,7 +419,7 @@ File_IsRemote(ConstUnicode pathName) // IN: Path name
*/
Bool
-File_IsSymLink(ConstUnicode pathName) // IN:
+File_IsSymLink(const char *pathName) // IN:
{
struct stat statbuf;
@@ -461,16 +445,16 @@ File_IsSymLink(ConstUnicode pathName) // IN:
*----------------------------------------------------------------------
*/
-Unicode
-File_Cwd(ConstUnicode drive) // IN:
+char *
+File_Cwd(const char *drive) // IN:
{
size_t size;
char *buffer;
- Unicode path;
+ char *path;
if ((drive != NULL) && !Unicode_IsEmpty(drive)) {
Warning(LGPFX" %s: Drive letter %s on Linux?\n", __FUNCTION__,
- UTF8(drive));
+ drive);
}
size = FILE_PATH_GROW_SIZE;
@@ -528,14 +512,14 @@ File_Cwd(ConstUnicode drive) // IN:
*----------------------------------------------------------------------
*/
-static Unicode
-FileStripFwdSlashes(ConstUnicode pathName) // IN:
+static char *
+FileStripFwdSlashes(const char *pathName) // IN:
{
char *ptr;
char *path;
char *cptr;
char *prev;
- Unicode result;
+ char *result;
ASSERT(pathName);
@@ -590,11 +574,11 @@ FileStripFwdSlashes(ConstUnicode pathName) // IN:
*----------------------------------------------------------------------
*/
-Unicode
-File_FullPath(ConstUnicode pathName) // IN:
+char *
+File_FullPath(const char *pathName) // IN:
{
- Unicode cwd;
- Unicode ret;
+ char *cwd;
+ char *ret;
if ((pathName != NULL) && File_IsFullPath(pathName)) {
cwd = NULL;
@@ -613,17 +597,17 @@ File_FullPath(ConstUnicode pathName) // IN:
ret = FileStripFwdSlashes(pathName);
}
} else {
- Unicode path = Unicode_Join(cwd, DIRSEPS, pathName, NULL);
+ char *path = Unicode_Join(cwd, DIRSEPS, pathName, NULL);
ret = Posix_RealPath(path);
if (ret == NULL) {
ret = FileStripFwdSlashes(path);
}
- Unicode_Free(path);
+ free(path);
}
- Unicode_Free(cwd);
+ free(cwd);
return ret;
}
@@ -646,7 +630,7 @@ File_FullPath(ConstUnicode pathName) // IN:
*/
Bool
-File_IsFullPath(ConstUnicode pathName) // IN:
+File_IsFullPath(const char *pathName) // IN:
{
/* start with a slash? */
return (pathName == NULL) ? FALSE :
@@ -673,7 +657,7 @@ File_IsFullPath(ConstUnicode pathName) // IN:
*/
Bool
-File_GetTimes(ConstUnicode pathName, // IN:
+File_GetTimes(const char *pathName, // IN:
VmTimeType *createTime, // OUT: Windows NT time format
VmTimeType *accessTime, // OUT: Windows NT time format
VmTimeType *writeTime, // OUT: Windows NT time format
@@ -690,7 +674,7 @@ File_GetTimes(ConstUnicode pathName, // IN:
if (Posix_Lstat(pathName, &statBuf) == -1) {
Log(LGPFX" %s: error stating file \"%s\": %s\n", __FUNCTION__,
- UTF8(pathName), Err_Errno2String(errno));
+ pathName, Err_Errno2String(errno));
return FALSE;
}
@@ -813,7 +797,7 @@ File_GetTimes(ConstUnicode pathName, // IN:
*/
Bool
-File_SetTimes(ConstUnicode pathName, // IN:
+File_SetTimes(const char *pathName, // IN:
VmTimeType createTime, // IN: ignored
VmTimeType accessTime, // IN: Windows NT time format
VmTimeType writeTime, // IN: Windows NT time format
@@ -832,7 +816,7 @@ File_SetTimes(ConstUnicode pathName, // IN:
path = Unicode_GetAllocBytes(pathName, STRING_ENCODING_DEFAULT);
if (path == NULL) {
Log(LGPFX" %s: failed to convert \"%s\" to current encoding\n",
- __FUNCTION__, UTF8(pathName));
+ __FUNCTION__, pathName);
return FALSE;
}
@@ -841,7 +825,7 @@ File_SetTimes(ConstUnicode pathName, // IN:
if (err != 0) {
Log(LGPFX" %s: error stating file \"%s\": %s\n", __FUNCTION__,
- UTF8(pathName), Err_Errno2String(err));
+ pathName, Err_Errno2String(err));
free(path);
return FALSE;
@@ -882,7 +866,7 @@ File_SetTimes(ConstUnicode pathName, // IN:
if (err != 0) {
Log(LGPFX" %s: utimes error on file \"%s\": %s\n", __FUNCTION__,
- UTF8(pathName), Err_Errno2String(err));
+ pathName, Err_Errno2String(err));
return FALSE;
}
@@ -908,15 +892,15 @@ File_SetTimes(ConstUnicode pathName, // IN:
*/
Bool
-File_SetFilePermissions(ConstUnicode pathName, // IN:
- int perms) // IN: permissions
+File_SetFilePermissions(const char *pathName, // IN:
+ int perms) // IN: permissions
{
ASSERT(pathName);
if (Posix_Chmod(pathName, perms) == -1) {
/* The error is not critical, just log it. */
Log(LGPFX" %s: failed to change permissions on file \"%s\": %s\n",
- __FUNCTION__, UTF8(pathName), Err_Errno2String(errno));
+ __FUNCTION__, pathName, Err_Errno2String(errno));
return FALSE;
}
@@ -953,10 +937,10 @@ File_SetFilePermissions(ConstUnicode pathName, // IN:
*/
static Bool
-FilePosixGetParent(Unicode *canPath) // IN/OUT: Canonical file path
+FilePosixGetParent(char **canPath) // IN/OUT: Canonical file path
{
- Unicode pathName;
- Unicode baseName;
+ char *pathName;
+ char *baseName;
ASSERT(canPath);
ASSERT(File_IsFullPath(*canPath));
@@ -967,22 +951,22 @@ FilePosixGetParent(Unicode *canPath) // IN/OUT: Canonical file path
File_GetPathName(*canPath, &pathName, &baseName);
- Unicode_Free(*canPath);
+ free(*canPath);
if (Unicode_IsEmpty(pathName)) {
/* empty string which denotes "/" */
- Unicode_Free(pathName);
+ free(pathName);
*canPath = Unicode_Duplicate("/");
} else {
if (Unicode_IsEmpty(baseName)) { // Directory
File_GetPathName(pathName, canPath, NULL);
- Unicode_Free(pathName);
+ free(pathName);
} else { // File
*canPath = pathName;
}
}
- Unicode_Free(baseName);
+ free(baseName);
return FALSE;
}
@@ -1003,7 +987,7 @@ FilePosixGetParent(Unicode *canPath) // IN/OUT: Canonical file path
*/
Bool
-File_GetParent(Unicode *canPath) // IN/OUT: Canonical file path
+File_GetParent(char **canPath) // IN/OUT: Canonical file path
{
return FilePosixGetParent(canPath);
}
@@ -1029,12 +1013,12 @@ File_GetParent(Unicode *canPath) // IN/OUT: Canonical file path
*/
static Bool
-FileGetStats(ConstUnicode pathName, // IN:
+FileGetStats(const char *pathName, // IN:
Bool doNotAscend, // IN:
struct statfs *pstatfsbuf) // OUT:
{
Bool retval = TRUE;
- Unicode dupPath = NULL;
+ char *dupPath = NULL;
while (Posix_Statfs(dupPath ? dupPath : pathName,
pstatfsbuf) == -1) {
@@ -1051,7 +1035,7 @@ FileGetStats(ConstUnicode pathName, // IN:
FilePosixGetParent(&dupPath);
}
- Unicode_Free(dupPath);
+ free(dupPath);
return retval;
}
@@ -1077,11 +1061,11 @@ FileGetStats(ConstUnicode pathName, // IN:
*/
uint64
-File_GetFreeSpace(ConstUnicode pathName, // IN: File name
- Bool doNotAscend) // IN: Do not ascend dir chain
+File_GetFreeSpace(const char *pathName, // IN: File name
+ Bool doNotAscend) // IN: Do not ascend dir chain
{
uint64 ret;
- Unicode fullPath;
+ char *fullPath;
struct statfs statfsbuf;
fullPath = File_FullPath(pathName);
@@ -1096,7 +1080,7 @@ File_GetFreeSpace(ConstUnicode pathName, // IN: File name
ret = -1;
}
- Unicode_Free(fullPath);
+ free(fullPath);
return ret;
}
@@ -1121,13 +1105,13 @@ File_GetFreeSpace(ConstUnicode pathName, // IN: File name
*/
int
-File_GetVMFSAttributes(ConstUnicode pathName, // IN: File/dir to test
+File_GetVMFSAttributes(const char *pathName, // IN: File/dir to test
FS_PartitionListResult **fsAttrs) // IN/OUT: VMFS Info
{
int fd;
int ret;
- Unicode fullPath;
- Unicode directory = NULL;
+ char *fullPath;
+ char *directory = NULL;
fullPath = File_FullPath(pathName);
if (fullPath == NULL) {
@@ -1142,7 +1126,7 @@ File_GetVMFSAttributes(ConstUnicode pathName, // IN: File/dir to tes
}
if (!HostType_OSIsVMK()) {
- Log(LGPFX" %s: File %s not on VMFS volume\n", __func__, UTF8(pathName));
+ Log(LGPFX" %s: File %s not on VMFS volume\n", __func__, pathName);
ret = -1;
goto bail;
}
@@ -1157,7 +1141,7 @@ File_GetVMFSAttributes(ConstUnicode pathName, // IN: File/dir to tes
fd = Posix_Open(directory, O_RDONLY, 0);
if (fd == -1) {
- Log(LGPFX" %s: could not open %s: %s\n", __func__, UTF8(pathName),
+ Log(LGPFX" %s: could not open %s: %s\n", __func__, pathName,
Err_Errno2String(errno));
ret = -1;
free(*fsAttrs);
@@ -1176,8 +1160,8 @@ File_GetVMFSAttributes(ConstUnicode pathName, // IN: File/dir to tes
close(fd);
bail:
- Unicode_Free(fullPath);
- Unicode_Free(directory);
+ free(fullPath);
+ free(directory);
return ret;
}
@@ -1207,9 +1191,9 @@ bail:
*/
int
-File_GetVMFSFSType(ConstUnicode pathName, // IN: File name to test
- int fd, // IN: fd of an already opened file
- uint16 *fsTypeNum) // OUT: Filesystem type number
+File_GetVMFSFSType(const char *pathName, // IN: File name to test
+ int fd, // IN: fd of an already opened file
+ uint16 *fsTypeNum) // OUT: Filesystem type number
{
int ret, savedErrno;
Bool fdArg = (fd >= 0); /* fd or pathname ? */
@@ -1223,7 +1207,7 @@ File_GetVMFSFSType(ConstUnicode pathName, // IN: File name to test
fd = Posix_Open(pathName, O_RDONLY, 0);
if (fd < 0) {
savedErrno = errno;
- Log(LGPFX" %s : Could not open %s : %s\n", __func__, UTF8(pathName),
+ Log(LGPFX" %s : Could not open %s : %s\n", __func__, pathName,
Err_Errno2String(savedErrno));
goto exit;
}
@@ -1240,7 +1224,7 @@ File_GetVMFSFSType(ConstUnicode pathName, // IN: File name to test
if (ret == -1) {
Log(LGPFX" %s : Could not get filesystem type for %s (fd %d) : %s\n",
- __func__, (!fdArg ? UTF8(pathName) : "__na__"), fd,
+ __func__, (!fdArg ? pathName : "__na__"), fd,
Err_Errno2String(savedErrno));
goto exit;
}
@@ -1273,8 +1257,8 @@ exit:
*/
int
-File_GetVMFSVersion(ConstUnicode pathName, // IN: File name to test
- uint32 *versionNum) // OUT: Version number
+File_GetVMFSVersion(const char *pathName, // IN: File name to test
+ uint32 *versionNum) // OUT: Version number
{
int ret = -1;
FS_PartitionListResult *fsAttrs = NULL;
@@ -1319,8 +1303,8 @@ exit:
*/
int
-File_GetVMFSBlockSize(ConstUnicode pathName, // IN: File name to test
- uint32 *blockSize) // IN/OUT: VMFS block size
+File_GetVMFSBlockSize(const char *pathName, // IN: File name to test
+ uint32 *blockSize) // IN/OUT: VMFS block size
{
int ret = -1;
FS_PartitionListResult *fsAttrs = NULL;
@@ -1367,7 +1351,7 @@ exit:
*/
int
-File_GetVMFSMountInfo(ConstUnicode pathName, // IN:
+File_GetVMFSMountInfo(const char *pathName, // IN:
char **fsType, // OUT:
uint32 *version, // OUT:
char **remoteIP, // OUT:
@@ -1383,19 +1367,17 @@ File_GetVMFSMountInfo(ConstUnicode pathName, // IN:
return -1;
}
- // Get file IP and mount point
+ /* Get file IP and mount point */
ret = File_GetVMFSAttributes(pathName, &fsAttrs);
if (ret >= 0 && fsAttrs) {
*version = fsAttrs->versionNumber;
*fsType = Util_SafeStrdup(fsAttrs->fsType);
- if (memcmp(fsAttrs->fsType, FS_NFS_ON_ESX, sizeof(FS_NFS_ON_ESX)) == 0) {
- /*
- * logicalDevice from NFS3 client contains remote IP and remote
- * mount point, separated by space. Split them out. If there is
- * no space then this is probably NFS41 client, and we cannot
- * obtain its remote mount point details at this time.
- */
+ /*
+ * We only compare the first 3 characters 'NFS'xx.
+ * This will cover both NFSv3 and NFSv4.1.
+ */
+ if (strncmp(fsAttrs->fsType, FS_NFS_ON_ESX, FS_NFS_PREFIX_LEN) == 0) {
char *sep = strchr(fsAttrs->logicalDevice, ' ');
if (sep) {
@@ -1437,7 +1419,7 @@ File_GetVMFSMountInfo(ConstUnicode pathName, // IN:
*/
static Bool
-FileIsVMFS(ConstUnicode pathName) // IN:
+FileIsVMFS(const char *pathName) // IN:
{
Bool result = FALSE;
@@ -1482,7 +1464,7 @@ FileIsVMFS(ConstUnicode pathName) // IN:
*/
Bool
-File_SupportsZeroedThick(ConstUnicode pathName) // IN:
+File_SupportsZeroedThick(const char *pathName) // IN:
{
return FileIsVMFS(pathName);
}
@@ -1508,7 +1490,7 @@ File_SupportsZeroedThick(ConstUnicode pathName) // IN:
*/
Bool
-File_SupportsMultiWriter(ConstUnicode pathName) // IN:
+File_SupportsMultiWriter(const char *pathName) // IN:
{
return FileIsVMFS(pathName);
}
@@ -1532,10 +1514,10 @@ File_SupportsMultiWriter(ConstUnicode pathName) // IN:
*/
uint64
-File_GetCapacity(ConstUnicode pathName) // IN: Path name
+File_GetCapacity(const char *pathName) // IN: Path name
{
uint64 ret;
- Unicode fullPath;
+ char *fullPath;
struct statfs statfsbuf;
fullPath = File_FullPath(pathName);
@@ -1550,7 +1532,7 @@ File_GetCapacity(ConstUnicode pathName) // IN: Path name
ret = -1;
}
- Unicode_Free(fullPath);
+ free(fullPath);
return ret;
}
@@ -1567,7 +1549,7 @@ File_GetCapacity(ConstUnicode pathName) // IN: Path name
* 'path' can be relative (including empty) or absolute, and any number
* of non-existing components at the end of 'path' are simply ignored.
*
- * XXX: On Posix systems, we choose the underlying device's name as the
+ * XXX: On POSIX systems, we choose the underlying device's name as the
* unique ID. I make no claim that this is 100% unique so if you
* need this functionality to be 100% perfect, I suggest you think
* about it more deeply than I did. -meccleston
@@ -1842,7 +1824,7 @@ retry:
/* Find the nearest ancestor of 'canPath' that is a mount point. */
for (;;) {
char *x;
- Bool bind;
+ Bool bind = FALSE;
char *ptr;
ptr = FilePosixLookupMountPoint(canPath, &bind);
@@ -1887,7 +1869,7 @@ retry:
if (*diff != '\0') {
Str_Sprintf(canPath, sizeof canPath, "%s%s",
- strlen(ptr) > 1 ? ptr : "", diff);
+ strlen(ptr) > 1 ? ptr : "", diff);
} else {
Str_Strcpy(canPath, ptr, sizeof canPath);
}
@@ -2019,8 +2001,8 @@ FilePosixNearestExistingAncestor(char const *path) // IN: File path
*/
Bool
-File_IsSameFile(ConstUnicode path1, // IN:
- ConstUnicode path2) // IN:
+File_IsSameFile(const char *path1, // IN:
+ const char *path2) // IN:
{
struct stat st1;
struct stat st2;
@@ -2057,7 +2039,7 @@ File_IsSameFile(ConstUnicode path1, // IN:
return FALSE;
}
- if (HostType_OSIsPureVMK()) {
+ if (HostType_OSIsVMK()) {
/*
* On ESX, post change 1074635 the st_dev field of the stat structure
* is valid and differentiates between resident devices or NFS file
@@ -2136,8 +2118,8 @@ File_IsSameFile(ConstUnicode path1, // IN:
*/
Bool
-File_Replace(ConstUnicode oldName, // IN: old file
- ConstUnicode newName) // IN: new file
+File_Replace(const char *oldName, // IN: old file
+ const char *newName) // IN: new file
{
int status = 0;
Bool result = FALSE;
@@ -2278,25 +2260,25 @@ FilePosixGetMaxOrSupportsFileSize(FileIODescriptor *fd, // IN:
*/
static Bool
-FilePosixCreateTestGetMaxOrSupportsFileSize(ConstUnicode dirName,// IN: test dir
+FilePosixCreateTestGetMaxOrSupportsFileSize(const char *dirName, // IN: test dir
uint64 *fileSize, // IN/OUT:
Bool getMaxFileSize) // IN:
{
Bool retVal;
int posixFD;
- Unicode temp;
- Unicode path;
+ char *temp;
+ char *path;
FileIODescriptor fd;
ASSERT(fileSize);
temp = Unicode_Append(dirName, "/.vmBigFileTest");
posixFD = File_MakeSafeTemp(temp, &path);
- Unicode_Free(temp);
+ free(temp);
if (posixFD == -1) {
Log(LGPFX" %s: Failed to create temporary file in dir: %s\n", __func__,
- UTF8(dirName));
+ dirName);
return FALSE;
}
@@ -2309,7 +2291,7 @@ FilePosixCreateTestGetMaxOrSupportsFileSize(ConstUnicode dirName,// IN: test dir
FileIO_Close(&fd);
File_Unlink(path);
- Unicode_Free(path);
+ free(path);
return retVal;
}
@@ -2336,21 +2318,21 @@ FilePosixCreateTestGetMaxOrSupportsFileSize(ConstUnicode dirName,// IN: test dir
*/
static Bool
-FileVMKGetMaxFileSize(ConstUnicode pathName, // IN:
- uint64 *maxFileSize) // OUT:
+FileVMKGetMaxFileSize(const char *pathName, // IN:
+ uint64 *maxFileSize) // OUT:
{
int fd;
Bool retval = TRUE;
- Unicode fullPath;
+ char *fullPath;
- Unicode dirPath = NULL;
+ char *dirPath = NULL;
ASSERT(maxFileSize);
fullPath = File_FullPath(pathName);
if (fullPath == NULL) {
Log(LGPFX" %s: Failed to get the full path for %s\n", __func__,
- UTF8(pathName));
+ pathName);
retval = FALSE;
goto bail;
}
@@ -2369,22 +2351,22 @@ FileVMKGetMaxFileSize(ConstUnicode pathName, // IN:
*/
fd = Posix_Open(dirPath, O_RDONLY, 0);
if (fd == -1) {
- Log(LGPFX" %s: could not open %s: %s\n", __func__, UTF8(dirPath),
+ Log(LGPFX" %s: could not open %s: %s\n", __func__, dirPath,
Err_Errno2String(errno));
retval = FALSE;
goto bail;
}
- if(ioctl(fd, IOCTLCMD_VMFS_GET_MAX_FILE_SIZE, maxFileSize) == -1) {
+ if (ioctl(fd, IOCTLCMD_VMFS_GET_MAX_FILE_SIZE, maxFileSize) == -1) {
Log(LGPFX" %s: Could not get max file size for path: %s, error: %s\n",
- __func__, UTF8(pathName), Err_Errno2String(errno));
+ __func__, pathName, Err_Errno2String(errno));
retval = FALSE;
}
close(fd);
bail:
- Unicode_Free(fullPath);
- Unicode_Free(dirPath);
+ free(fullPath);
+ free(dirPath);
return retval;
}
@@ -2418,9 +2400,9 @@ bail:
*/
static Bool
-FileVMKGetMaxOrSupportsFileSize(ConstUnicode pathName, // IN:
- uint64 *fileSize, // IN/OUT:
- Bool getMaxFileSize) // IN:
+FileVMKGetMaxOrSupportsFileSize(const char *pathName, // IN:
+ uint64 *fileSize, // IN/OUT:
+ Bool getMaxFileSize) // IN:
{
#if defined(VMX86_SERVER)
FS_PartitionListResult *fsAttrs = NULL;
@@ -2480,8 +2462,8 @@ FileVMKGetMaxOrSupportsFileSize(ConstUnicode pathName, // IN:
return *fileSize <= maxFileSize;
}
} else {
- Unicode fullPath;
- Unicode parentPath;
+ char *fullPath;
+ char *parentPath;
Bool supported;
Log(LGPFX" %s: Trying create file and seek approach.\n", __func__);
@@ -2501,8 +2483,8 @@ FileVMKGetMaxOrSupportsFileSize(ConstUnicode pathName, // IN:
getMaxFileSize);
free(fsAttrs);
- Unicode_Free(fullPath);
- Unicode_Free(parentPath);
+ free(fullPath);
+ free(parentPath);
return supported;
}
@@ -2541,12 +2523,12 @@ FileVMKGetMaxOrSupportsFileSize(ConstUnicode pathName, // IN:
*/
Bool
-FileGetMaxOrSupportsFileSize(ConstUnicode pathName, // IN:
- uint64 *fileSize, // IN/OUT:
- Bool getMaxFileSize) // IN:
+FileGetMaxOrSupportsFileSize(const char *pathName, // IN:
+ uint64 *fileSize, // IN/OUT:
+ Bool getMaxFileSize) // IN:
{
- Unicode fullPath;
- Unicode folderPath;
+ char *fullPath;
+ char *folderPath;
Bool retval = FALSE;
ASSERT(fileSize);
@@ -2600,10 +2582,10 @@ FileGetMaxOrSupportsFileSize(ConstUnicode pathName, // IN:
retval = FilePosixCreateTestGetMaxOrSupportsFileSize(folderPath, fileSize,
getMaxFileSize);
- Unicode_Free(folderPath);
+ free(folderPath);
out:
- Unicode_Free(fullPath);
+ free(fullPath);
return retval;
}
@@ -2630,8 +2612,8 @@ out:
*/
Bool
-File_GetMaxFileSize(ConstUnicode pathName, // IN:
- uint64 *maxFileSize) // OUT:
+File_GetMaxFileSize(const char *pathName, // IN:
+ uint64 *maxFileSize) // OUT:
{
Bool result;
@@ -2674,8 +2656,8 @@ File_GetMaxFileSize(ConstUnicode pathName, // IN:
*/
Bool
-File_SupportsFileSize(ConstUnicode pathName, // IN:
- uint64 fileSize) // IN:
+File_SupportsFileSize(const char *pathName, // IN:
+ uint64 fileSize) // IN:
{
/*
* All supported filesystems can hold at least 2GB-1 bytes files.
@@ -2713,8 +2695,8 @@ File_SupportsFileSize(ConstUnicode pathName, // IN:
*/
int
-FileCreateDirectory(ConstUnicode pathName, // IN:
- int mask) // IN:
+FileCreateDirectory(const char *pathName, // IN:
+ int mask) // IN:
{
int err;
@@ -2741,7 +2723,7 @@ FileCreateDirectory(ConstUnicode pathName, // IN:
* Side effects:
* If ids is provided and the function succeeds, memory is
* allocated for both the unicode strings and the array itself
- * and must be freed. (See Unicode_FreeList.)
+ * and must be freed. (See Util_FreeStringList.)
* The memory allocated for the array may be larger than necessary.
* The caller may trim it with realloc() if it cares.
*
@@ -2756,7 +2738,7 @@ FileKeyDispose(const char *key, // IN:
void *value, // IN:
void *clientData) // IN:
{
- Unicode_Free((void *) key);
+ free((void *) key);
return 0;
}
@@ -2774,8 +2756,8 @@ FileUnique(const char *key, // IN:
}
int
-File_ListDirectory(ConstUnicode pathName, // IN:
- Unicode **ids) // OUT: relative paths
+File_ListDirectory(const char *pathName, // IN:
+ char ***ids) // OUT: relative paths
{
int err;
DIR *dir;
@@ -2812,7 +2794,7 @@ File_ListDirectory(ConstUnicode pathName, // IN:
/* Don't create the file list if we aren't providing it to the caller. */
if (ids) {
- Unicode id;
+ char *id;
if (Unicode_IsBufferValid(entry->d_name, -1,
STRING_ENCODING_DEFAULT)) {
@@ -2824,7 +2806,7 @@ File_ListDirectory(ConstUnicode pathName, // IN:
Warning("%s: file '%s' in directory '%s' cannot be converted to "
"UTF8\n", __FUNCTION__, pathName, id);
- Unicode_Free(id);
+ free(id);
id = Unicode_Duplicate(UNICODE_SUBSTITUTION_CHAR
UNICODE_SUBSTITUTION_CHAR
@@ -2843,7 +2825,7 @@ File_ListDirectory(ConstUnicode pathName, // IN:
if (HashTable_Insert(hash, id, NULL)) {
count++;
} else {
- Unicode_Free(id);
+ free(id);
}
} else {
count++;
@@ -2874,7 +2856,33 @@ File_ListDirectory(ConstUnicode pathName, // IN:
}
-#if CAN_USE_FTS
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * File_WalkDirectoryEnd --
+ *
+ * End the directory traversal.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The context is now invalid.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+File_WalkDirectoryEnd(WalkDirContext context) // IN:
+{
+ if (context != NULL) {
+ if (context->cnt > 0) {
+ Util_FreeStringList(context->files, context->cnt);
+ }
+ free(context);
+ }
+}
+
/*
*-----------------------------------------------------------------------------
@@ -2886,12 +2894,6 @@ File_ListDirectory(ConstUnicode pathName, // IN:
* To read each entry, repeatedly pass the returned context to
* File_WalkDirectoryNext() until that function returns FALSE.
*
- * When done, pass the returned context to File_WalkDirectoryEnd().
- *
- * A pre-order, logical traversal will be completed; hard links and
- * symbolic links that do not cause a cycle are followed in the directory
- * traversal.
- *
* We assume no thread will change the working directory between the calls
* to File_WalkDirectoryStart and File_WalkDirectoryEnd.
*
@@ -2906,26 +2908,21 @@ File_ListDirectory(ConstUnicode pathName, // IN:
*/
WalkDirContext
-File_WalkDirectoryStart(ConstUnicode parentPath) // IN:
+File_WalkDirectoryStart(const char *parentPath) // IN:
{
- WalkDirContextImpl *context;
- char * const traversalRoots[] =
- { Unicode_GetAllocBytes(parentPath, STRING_ENCODING_DEFAULT), NULL };
+ WalkDirContextImpl *context = malloc(sizeof *context);
- context = malloc(sizeof *context);
- if (!context) {
- return NULL;
- }
+ if (context != NULL) {
+ context->files = NULL;
+ context->iter = 0;
+ context->cnt = File_ListDirectory(parentPath, &context->files);
- context->fts = fts_open(traversalRoots, FTS_LOGICAL|FTS_NOSTAT|FTS_NOCHDIR,
- NULL);
- if (!context->fts) {
- free(context);
- context = NULL;
+ if (context->cnt == -1) {
+ File_WalkDirectoryEnd(context);
+ context = NULL;
+ }
}
- free(traversalRoots[0]);
-
return context;
}
@@ -2941,8 +2938,8 @@ File_WalkDirectoryStart(ConstUnicode parentPath) // IN:
* Results:
* TRUE iff the traversal hasn't completed.
*
- * If TRUE, *path holds an allocated string prefixed by parentPath that
- * the caller must free (see Unicode_Free).
+ * If TRUE, *path holds an allocated string of a directory entry that the
+ * caller must free (see free).
*
* If FALSE, errno is 0 iff the walk completed sucessfully.
*
@@ -2954,112 +2951,22 @@ File_WalkDirectoryStart(ConstUnicode parentPath) // IN:
Bool
File_WalkDirectoryNext(WalkDirContext context, // IN:
- Unicode *path) // OUT:
+ char **path) // OUT:
{
- FTSENT *nextEntry;
-
ASSERT(context);
- ASSERT(context->fts);
ASSERT(path);
- do {
- nextEntry = fts_read(context->fts);
-
- /*
- * We'll skip any entries that cannot be read, are errors, or
- * are the second traversal (post-order) of a directory.
- */
-
- if (nextEntry &&
- nextEntry->fts_info != FTS_DNR &&
- nextEntry->fts_info != FTS_ERR &&
- nextEntry->fts_info != FTS_DP) {
- *path = Unicode_AllocWithLength(nextEntry->fts_path,
- nextEntry->fts_pathlen,
- STRING_ENCODING_DEFAULT);
-
- return TRUE;
- }
- } while (nextEntry);
-
- return FALSE;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * File_WalkDirectoryEnd --
- *
- * End the directory traversal.
- *
- * Results:
- * None
- *
- * Side effects:
- * The context is now invalid.
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-File_WalkDirectoryEnd(WalkDirContext context) // IN:
-{
- ASSERT(context);
- ASSERT(context->fts);
+ errno = 0; // Any errors showed up at "start time".
- if (fts_close(context->fts) == -1) {
- Log(LGPFX" %s: failed to close fts: %p\n", __FUNCTION__, context->fts);
+ if (context->iter < context->cnt) {
+ *path = Util_SafeStrdup(context->files[context->iter++]);
+ return TRUE;
}
- free((WalkDirContextImpl *)context);
-}
-
-#else
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * File_WalkDirectoryStart --
- * File_WalkDirectoryNext --
- * File_WalkDirectoryEnd --
- *
- * XXX FTS is not supported on this posix variant. See above.
- *
- * Results:
- * None
- *
- * Side effects:
- * ASSERTs.
- *
- *-----------------------------------------------------------------------------
- */
-
-WalkDirContext
-File_WalkDirectoryStart(ConstUnicode parentPath) // IN:
-{
- NOT_IMPLEMENTED();
-}
-
-
-Bool
-File_WalkDirectoryNext(WalkDirContext context, // IN:
- Unicode *path) // OUT:
-{
- NOT_IMPLEMENTED();
-}
-
-void
-File_WalkDirectoryEnd(WalkDirContext context) // IN:
-{
- NOT_IMPLEMENTED();
+ return FALSE;
}
-#endif // CAN_USE_FTS
-
-
/*
*----------------------------------------------------------------------
*
@@ -3151,7 +3058,7 @@ end:
*/
Bool
-FileIsWritableDir(ConstUnicode dirName) // IN:
+FileIsWritableDir(const char *dirName) // IN:
{
int err;
uid_t euid;
@@ -3203,7 +3110,7 @@ FileIsWritableDir(ConstUnicode dirName) // IN:
*/
Bool
-File_MakeCfgFileExecutable(ConstUnicode pathName) // IN:
+File_MakeCfgFileExecutable(const char *pathName) // IN:
{
struct stat s;
@@ -3242,7 +3149,7 @@ File_MakeCfgFileExecutable(ConstUnicode pathName) // IN:
*/
int64
-File_GetSizeAlternate(ConstUnicode pathName) // IN:
+File_GetSizeAlternate(const char *pathName) // IN:
{
return File_GetSize(pathName);
}
@@ -3269,7 +3176,7 @@ File_GetSizeAlternate(ConstUnicode pathName) // IN:
*/
Bool
-File_IsCharDevice(ConstUnicode pathName) // IN:
+File_IsCharDevice(const char *pathName) // IN:
{
FileData fileData;
diff --git a/open-vm-tools/lib/file/fileStandAlone.c b/open-vm-tools/lib/file/fileStandAlone.c
index 57e526cc..eb32050d 100644
--- a/open-vm-tools/lib/file/fileStandAlone.c
+++ b/open-vm-tools/lib/file/fileStandAlone.c
@@ -42,6 +42,7 @@
#include "vmware.h"
#include "util.h"
#include "str.h"
+#include "strutil.h"
#include "posix.h"
#include "file.h"
@@ -66,7 +67,7 @@
*/
int64
-File_GetModTime(ConstUnicode pathName) // IN:
+File_GetModTime(const char *pathName) // IN:
{
int64 theTime;
struct stat statbuf;
@@ -91,7 +92,7 @@ File_GetModTime(ConstUnicode pathName) // IN:
*
* Results:
* As described.
- *
+ *
* Side effects:
* None.
*
@@ -99,7 +100,7 @@ File_GetModTime(ConstUnicode pathName) // IN:
*/
UnicodeIndex
-FileFirstSlashIndex(ConstUnicode pathName, // IN:
+FileFirstSlashIndex(const char *pathName, // IN:
UnicodeIndex startIndex) // IN:
{
UnicodeIndex firstFS;
@@ -138,7 +139,7 @@ FileFirstSlashIndex(ConstUnicode pathName, // IN:
*
* Results:
* As described.
- *
+ *
* Side effects:
* None.
*
@@ -146,7 +147,7 @@ FileFirstSlashIndex(ConstUnicode pathName, // IN:
*/
static UnicodeIndex
-FileLastSlashIndex(ConstUnicode pathName, // IN:
+FileLastSlashIndex(const char *pathName, // IN:
UnicodeIndex startIndex) // IN:
{
UnicodeIndex lastFS;
@@ -202,7 +203,7 @@ FileLastSlashIndex(ConstUnicode pathName, // IN:
*
* Results:
* As described.
- *
+ *
* Side effects:
* None.
*
@@ -210,14 +211,14 @@ FileLastSlashIndex(ConstUnicode pathName, // IN:
*/
void
-File_SplitName(ConstUnicode pathName, // IN:
- Unicode *volume, // OUT (OPT):
- Unicode *directory, // OUT (OPT):
- Unicode *base) // OUT (OPT):
+File_SplitName(const char *pathName, // IN:
+ char **volume, // OUT/OPT:
+ char **directory, // OUT/OPT:
+ char **base) // OUT/OPT:
{
- Unicode vol;
- Unicode dir;
- Unicode bas;
+ char *vol;
+ char *dir;
+ char *bas;
UnicodeIndex volEnd;
UnicodeIndex length;
UnicodeIndex baseBegin;
@@ -234,8 +235,8 @@ File_SplitName(ConstUnicode pathName, // IN:
#if defined(_WIN32)
pathLen = Unicode_LengthInCodePoints(pathName);
if ((pathLen > 2) &&
- (Unicode_StartsWith(pathName, "\\\\") ||
- Unicode_StartsWith(pathName, "//"))) {
+ (StrUtil_StartsWith(pathName, "\\\\") ||
+ StrUtil_StartsWith(pathName, "//"))) {
/* UNC path */
volEnd = FileFirstSlashIndex(pathName, 2);
@@ -298,19 +299,19 @@ File_SplitName(ConstUnicode pathName, // IN:
if (volume) {
*volume = vol;
} else {
- Unicode_Free(vol);
+ free(vol);
}
if (directory) {
*directory = dir;
} else {
- Unicode_Free(dir);
+ free(dir);
}
if (base) {
*base = bas;
} else {
- Unicode_Free(bas);
+ free(bas);
}
}
@@ -351,12 +352,12 @@ File_SplitName(ConstUnicode pathName, // IN:
*---------------------------------------------------------------------------
*/
-Unicode
-File_PathJoin(ConstUnicode dirName, // IN:
- ConstUnicode baseName) // IN: See above.
+char *
+File_PathJoin(const char *dirName, // IN:
+ const char *baseName) // IN: See above.
{
- Unicode result;
- Unicode newDir = NULL;
+ char *result;
+ char *newDir = NULL;
ASSERT(dirName);
ASSERT(baseName);
@@ -366,7 +367,7 @@ File_PathJoin(ConstUnicode dirName, // IN:
*/
#if defined(_WIN32)
{
- ConstUnicode oldBaseName = baseName;
+ const char *oldBaseName = baseName;
/*
* Reject drive letters in baseName.
@@ -396,7 +397,7 @@ File_PathJoin(ConstUnicode dirName, // IN:
newDir = File_StripSlashes(dirName);
result = Unicode_Join(newDir, DIRSEPS, baseName, NULL);
- Unicode_Free(newDir);
+ free(newDir);
return result;
}
@@ -420,28 +421,28 @@ File_PathJoin(ConstUnicode dirName, // IN:
* A NULL pointer may be passed for one or more OUT parameters,
* in which case that parameter is not returned.
*
- * Results:
+ * Results:
* As described.
*
- * Side effects:
+ * Side effects:
* The return values must be freed.
*
*---------------------------------------------------------------------------
*/
-void
-File_GetPathName(ConstUnicode fullPath, // IN:
- Unicode *pathName, // OUT (OPT):
- Unicode *baseName) // OUT (OPT):
+void
+File_GetPathName(const char *fullPath, // IN:
+ char **pathName, // OUT/OPT:
+ char **baseName) // OUT/OPT:
{
- Unicode volume;
+ char *volume;
UnicodeIndex len;
UnicodeIndex curLen;
File_SplitName(fullPath, &volume, pathName, baseName);
if (pathName == NULL) {
- Unicode_Free(volume);
+ free(volume);
return;
}
@@ -450,12 +451,12 @@ File_GetPathName(ConstUnicode fullPath, // IN:
*/
if (!Unicode_IsEmpty(volume)) {
- Unicode temp = Unicode_Append(volume, *pathName);
+ char *temp = Unicode_Append(volume, *pathName);
- Unicode_Free(*pathName);
+ free(*pathName);
*pathName = temp;
}
- Unicode_Free(volume);
+ free(volume);
/*
* Remove any trailing directory separator characters.
@@ -471,9 +472,9 @@ File_GetPathName(ConstUnicode fullPath, // IN:
}
if (curLen < len) {
- Unicode temp = Unicode_Substr(*pathName, 0, curLen);
+ char *temp = Unicode_Substr(*pathName, 0, curLen);
- Unicode_Free(*pathName);
+ free(*pathName);
*pathName = temp;
}
}
@@ -495,10 +496,13 @@ File_GetPathName(ConstUnicode fullPath, // IN:
*----------------------------------------------------------------------
*/
-Unicode
-File_StripSlashes(ConstUnicode path) // IN:
+char *
+File_StripSlashes(const char *path) // IN:
{
- Unicode result, volume, dir, base;
+ char *result;
+ char *volume;
+ char *dir;
+ char *base;
/*
* SplitName handles all drive letter/UNC/whatever cases, all we
@@ -526,16 +530,16 @@ File_StripSlashes(ConstUnicode path) // IN:
i--;
}
- Unicode_Free(dir);
+ free(dir);
dir = Unicode_AllocWithLength(dir2, i, STRING_ENCODING_UTF8);
free(dir2);
}
result = Unicode_Join(volume, dir, base, NULL);
- Unicode_Free(volume);
- Unicode_Free(dir);
- Unicode_Free(base);
+ free(volume);
+ free(dir);
+ free(base);
return result;
}
@@ -714,28 +718,28 @@ File_PrependToPath(const char *searchPath, // IN:
*-----------------------------------------------------------------------------
*/
-Unicode
-File_ReplaceExtension(ConstUnicode pathName, // IN:
- ConstUnicode newExtension, // IN:
- uint32 numExtensions, // IN:
- ...) // IN:
+char *
+File_ReplaceExtension(const char *pathName, // IN:
+ const char *newExtension, // IN:
+ uint32 numExtensions, // IN:
+ ...) // IN:
{
- Unicode path;
- Unicode base;
- Unicode result;
+ char *path;
+ char *base;
+ char *result;
va_list arguments;
UnicodeIndex index;
-
+
ASSERT(pathName);
ASSERT(newExtension);
- ASSERT(Unicode_StartsWith(newExtension, "."));
+ ASSERT(*newExtension == '.');
File_GetPathName(pathName, &path, &base);
index = Unicode_FindLast(base, ".");
if (index != UNICODE_INDEX_NOT_FOUND) {
- Unicode oldBase = base;
+ char *oldBase = base;
if (numExtensions) {
uint32 i;
@@ -748,9 +752,9 @@ File_ReplaceExtension(ConstUnicode pathName, // IN:
va_start(arguments, numExtensions);
for (i = 0; i < numExtensions ; i++) {
- Unicode oldExtension = va_arg(arguments, Unicode);
+ char *oldExtension = va_arg(arguments, char *);
- ASSERT(Unicode_StartsWith(oldExtension, "."));
+ ASSERT(*oldExtension == '.');
if (Unicode_CompareRange(base, index, -1,
oldExtension, 0, -1, FALSE) == 0) {
@@ -766,7 +770,7 @@ File_ReplaceExtension(ConstUnicode pathName, // IN:
}
if (oldBase != base) {
- Unicode_Free(oldBase);
+ free(oldBase);
}
}
@@ -776,8 +780,8 @@ File_ReplaceExtension(ConstUnicode pathName, // IN:
result = Unicode_Join(path, DIRSEPS, base, newExtension, NULL);
}
- Unicode_Free(path);
- Unicode_Free(base);
+ free(path);
+ free(base);
return result;
}
@@ -801,8 +805,8 @@ File_ReplaceExtension(ConstUnicode pathName, // IN:
*-----------------------------------------------------------------------------
*/
-Unicode
-File_RemoveExtension(ConstUnicode pathName) // IN:
+char *
+File_RemoveExtension(const char *pathName) // IN:
{
UnicodeIndex index;
diff --git a/open-vm-tools/lib/file/fileTemp.c b/open-vm-tools/lib/file/fileTemp.c
index 1b7f9423..0412788e 100644
--- a/open-vm-tools/lib/file/fileTemp.c
+++ b/open-vm-tools/lib/file/fileTemp.c
@@ -115,17 +115,17 @@ FileTempNum(Bool createTempFile, // IN:
*/
int
-File_MakeTempEx2(ConstUnicode dir, // IN:
+File_MakeTempEx2(const char *dir, // IN:
Bool createTempFile, // IN:
File_MakeTempCreateNameFunc *createNameFunc, // IN:
void *createNameFuncData, // IN:
- Unicode *presult) // OUT:
+ char **presult) // OUT:
{
uint32 i;
int fd = -1;
uint32 var = 0;
- Unicode path = NULL;
+ char *path = NULL;
if ((dir == NULL) || (createNameFunc == NULL)) {
errno = EFAULT;
@@ -138,10 +138,10 @@ File_MakeTempEx2(ConstUnicode dir, // IN:
*presult = NULL;
for (i = 0; i < (MAX_INT32 / 2); i++) {
- Unicode fileName;
+ char *fileName;
/* construct suffixed pathname to use */
- Unicode_Free(path);
+ free(path);
path = NULL;
/*
@@ -160,7 +160,7 @@ File_MakeTempEx2(ConstUnicode dir, // IN:
/* construct base full pathname to use */
path = Unicode_Join(dir, DIRSEPS, fileName, NULL);
- Unicode_Free(fileName);
+ free(fileName);
if (createTempFile) {
fd = Posix_Open(path, O_CREAT | O_EXCL | O_BINARY | O_RDWR, 0600);
@@ -177,7 +177,7 @@ File_MakeTempEx2(ConstUnicode dir, // IN:
if (errno != EEXIST) {
Log(LGPFX" Failed to create temporary %s \"%s\": %s.\n",
createTempFile ? "file" : "directory",
- UTF8(path), strerror(errno));
+ path, strerror(errno));
goto exit;
}
}
@@ -185,13 +185,13 @@ File_MakeTempEx2(ConstUnicode dir, // IN:
if (fd == -1) {
Warning(LGPFX" Failed to create temporary %s \"%s\": "
"The name space is full.\n",
- createTempFile ? "file" : "directory", UTF8(path));
+ createTempFile ? "file" : "directory", path);
errno = EAGAIN;
}
exit:
- Unicode_Free(path);
+ free(path);
return fd;
}
@@ -209,7 +209,7 @@ File_MakeTempEx2(ConstUnicode dir, // IN:
* 'num' specifies the nth time this function is called.
*
* 'data' specifies the payload that is specified when File_MakeTempEx2()
- * function is called. This points to a Unicode string.
+ * function is called. This points to a UTF8 string.
*
* Results:
* if successful, a dynamically allocated string with the basename of
@@ -221,7 +221,7 @@ File_MakeTempEx2(ConstUnicode dir, // IN:
*----------------------------------------------------------------------------
*/
-static Unicode
+static char *
FileMakeTempExCreateNameFunc(uint32 num, // IN:
void *data) // IN:
{
@@ -229,7 +229,7 @@ FileMakeTempExCreateNameFunc(uint32 num, // IN:
return NULL;
}
- return Unicode_Format("%s%u", (Unicode) data, num);
+ return Unicode_Format("%s%u", (char *) data, num);
}
@@ -258,9 +258,9 @@ FileMakeTempExCreateNameFunc(uint32 num, // IN:
*/
int
-File_MakeTempEx(ConstUnicode dir, // IN:
- ConstUnicode fileName, // IN:
- Unicode *presult) // OUT:
+File_MakeTempEx(const char *dir, // IN:
+ const char *fileName, // IN:
+ char **presult) // OUT:
{
return File_MakeTempEx2(dir, TRUE, FileMakeTempExCreateNameFunc,
(void *) fileName, presult);
@@ -287,19 +287,19 @@ File_MakeTempEx(ConstUnicode dir, // IN:
*----------------------------------------------------------------------
*/
-Unicode
-File_MakeSafeTempDir(ConstUnicode prefix) // IN:
+char *
+File_MakeSafeTempDir(const char *prefix) // IN:
{
- Unicode result = NULL;
- Unicode dir = File_GetSafeTmpDir(TRUE);
+ char *result = NULL;
+ char *dir = File_GetSafeTmpDir(TRUE);
if (dir != NULL) {
- ConstUnicode effectivePrefix = (prefix == NULL) ? "safeDir" : prefix;
+ const char *effectivePrefix = (prefix == NULL) ? "safeDir" : prefix;
File_MakeTempEx2(dir, FALSE, FileMakeTempExCreateNameFunc,
(void *) effectivePrefix, &result);
- Unicode_Free(dir);
+ free(dir);
}
return result;
@@ -324,12 +324,12 @@ File_MakeSafeTempDir(ConstUnicode prefix) // IN:
*/
int
-File_MakeSafeTemp(ConstUnicode tag, // IN (OPT):
- Unicode *presult) // OUT:
+File_MakeSafeTemp(const char *tag, // IN (OPT):
+ char **presult) // OUT:
{
int fd;
- Unicode dir = NULL;
- Unicode fileName = NULL;
+ char *dir = NULL;
+ char *fileName = NULL;
ASSERT(presult);
@@ -344,8 +344,8 @@ File_MakeSafeTemp(ConstUnicode tag, // IN (OPT):
fd = File_MakeTempEx(dir, fileName, presult);
- Unicode_Free(dir);
- Unicode_Free(fileName);
+ free(dir);
+ free(fileName);
return fd;
}
@@ -370,13 +370,14 @@ File_MakeSafeTemp(ConstUnicode tag, // IN (OPT):
*/
Bool
-File_DoesVolumeSupportAcls(ConstUnicode path) // IN:
+File_DoesVolumeSupportAcls(const char *path) // IN:
{
Bool succeeded = FALSE;
#if defined(_WIN32)
Bool res;
- Unicode vol, vol2;
+ char *vol;
+ char *vol2;
const utf16_t *vol2W;
DWORD fsFlags;
@@ -402,8 +403,8 @@ File_DoesVolumeSupportAcls(ConstUnicode path) // IN:
succeeded = TRUE;
exit:
- Unicode_Free(vol);
- Unicode_Free(vol2);
+ free(vol);
+ free(vol2);
#endif
return succeeded;
diff --git a/open-vm-tools/lib/file/fileTempPosix.c b/open-vm-tools/lib/file/fileTempPosix.c
index 67d75247..cbae9f35 100644
--- a/open-vm-tools/lib/file/fileTempPosix.c
+++ b/open-vm-tools/lib/file/fileTempPosix.c
@@ -36,10 +36,6 @@
# include <pwd.h>
#endif
-#if defined(sun)
-# include <procfs.h>
-#endif
-
#include "vmware.h"
#include "file.h"
#include "fileInt.h"
@@ -325,16 +321,16 @@ FileAcceptableSafeTmpDir(const char *dirname, // IN:
*-----------------------------------------------------------------------------
*/
-static Unicode
+static char *
FileFindExistingSafeTmpDir(uid_t userId, // IN:
const char *userName, // IN:
const char *baseTmpDir) // IN:
{
int i;
int numFiles;
- Unicode pattern;
- Unicode tmpDir = NULL;
- Unicode *fileList = NULL;
+ char *pattern;
+ char *tmpDir = NULL;
+ char **fileList = NULL;
/*
* We always use the pattern PRODUCT-USER-xxxx when creating
@@ -350,15 +346,14 @@ FileFindExistingSafeTmpDir(uid_t userId, // IN:
numFiles = File_ListDirectory(baseTmpDir, &fileList);
if (numFiles == -1) {
- Unicode_Free(pattern);
+ free(pattern);
return NULL;
}
for (i = 0; i < numFiles; i++) {
if (Unicode_StartsWith(fileList[i], pattern)) {
- Unicode path = Unicode_Join(baseTmpDir, DIRSEPS, fileList[i],
- NULL);
+ char *path = Unicode_Join(baseTmpDir, DIRSEPS, fileList[i], NULL);
if (File_IsDirectory(path) &&
FileAcceptableSafeTmpDir(path, userId)) {
@@ -366,12 +361,12 @@ FileFindExistingSafeTmpDir(uid_t userId, // IN:
break;
}
- Unicode_Free(path);
+ free(path);
}
}
- Unicode_FreeList(fileList, numFiles);
- Unicode_Free(pattern);
+ Util_FreeStringList(fileList, numFiles);
+ free(pattern);
return tmpDir;
}
diff --git a/open-vm-tools/lib/foundryMsg/foundryMsg.c b/open-vm-tools/lib/foundryMsg/foundryMsg.c
index 2cd8fb00..1af5b5c1 100644
--- a/open-vm-tools/lib/foundryMsg/foundryMsg.c
+++ b/open-vm-tools/lib/foundryMsg/foundryMsg.c
@@ -254,31 +254,19 @@ static const VixCommandInfo vixCommandInfoTable[] = {
VIX_COMMAND_CATEGORY_PRIVILEGED),
VIX_DEFINE_UNUSED_COMMAND,
- /*
- * vProbes are only available remotely through VIX, so we should
- * let them through. If they get added to the VMODL with their own
- * permissions, then we will have to revisit.
- */
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_GET_VPROBES_VERSION,
- VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED),
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_GET_VPROBES,
- VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED),
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_VPROBE_GET_GLOBALS,
- VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED),
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_VPROBE_LOAD,
- VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED),
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_VPROBE_RESET,
- VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED),
+ VIX_DEFINE_UNUSED_COMMAND,
+ VIX_DEFINE_UNUSED_COMMAND,
+ VIX_DEFINE_UNUSED_COMMAND,
+ VIX_DEFINE_UNUSED_COMMAND,
+ VIX_DEFINE_UNUSED_COMMAND,
VIX_DEFINE_UNUSED_COMMAND,
VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_CONNECT_HOST,
VIX_COMMAND_CATEGORY_PRIVILEGED),
VIX_DEFINE_UNUSED_COMMAND,
VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_CREATE_LINKED_CLONE,
VIX_COMMAND_CATEGORY_PRIVILEGED),
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_STOP_SNAPSHOT_LOG_RECORDING,
- VIX_COMMAND_CATEGORY_PRIVILEGED),
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_STOP_SNAPSHOT_LOG_PLAYBACK,
- VIX_COMMAND_CATEGORY_PRIVILEGED),
+ VIX_DEFINE_UNUSED_COMMAND,
+ VIX_DEFINE_UNUSED_COMMAND,
/*
* HOWTO: Adding a new Vix Command. Step 2b.
* Take the command you added to vixCommands.h, and add it to this
@@ -323,12 +311,9 @@ static const VixCommandInfo vixCommandInfoTable[] = {
VIX_COMMAND_CATEGORY_PRIVILEGED),
VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_HOT_REMOVE_DEVICE,
VIX_COMMAND_CATEGORY_PRIVILEGED),
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_DEBUGGER_ATTACH,
- VIX_COMMAND_CATEGORY_PRIVILEGED),
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_DEBUGGER_DETACH,
- VIX_COMMAND_CATEGORY_PRIVILEGED),
- VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_DEBUGGER_SEND_COMMAND,
- VIX_COMMAND_CATEGORY_PRIVILEGED),
+ VIX_DEFINE_UNUSED_COMMAND,
+ VIX_DEFINE_UNUSED_COMMAND,
+ VIX_DEFINE_UNUSED_COMMAND,
VIX_DEFINE_UNUSED_COMMAND,
VIX_DEFINE_UNUSED_COMMAND,
VIX_DEFINE_UNUSED_COMMAND,
diff --git a/open-vm-tools/lib/foundryMsg/vixTranslateErrOpenSource.c b/open-vm-tools/lib/foundryMsg/vixTranslateErrOpenSource.c
index 7edea511..3314cfd1 100644
--- a/open-vm-tools/lib/foundryMsg/vixTranslateErrOpenSource.c
+++ b/open-vm-tools/lib/foundryMsg/vixTranslateErrOpenSource.c
@@ -1,4 +1,3 @@
-
/*********************************************************
* Copyright (C) 2003-2015 VMware, Inc. All rights reserved.
*
@@ -62,7 +61,7 @@ Vix_TranslateGuestRegistryError(int systemError) // IN
{
VixError err = VIX_E_FAIL;
#ifdef _WIN32
- Unicode msg;
+ char *msg;
switch (systemError) {
case ERROR_INVALID_PARAMETER:
@@ -84,7 +83,7 @@ Vix_TranslateGuestRegistryError(int systemError) // IN
Log("Foundry operation failed with guest windows registry error: %s (%d), translated to %"FMT64"d\n",
msg, systemError, err);
- Unicode_Free(msg);
+ free(msg);
#endif
return err;
@@ -111,7 +110,7 @@ Vix_TranslateSystemError(int systemError) // IN
{
VixError err = VIX_E_FAIL;
#ifdef _WIN32
- Unicode msg;
+ char *msg;
switch (systemError) {
case ERROR_ACCESS_DENIED:
@@ -179,7 +178,7 @@ Vix_TranslateSystemError(int systemError) // IN
Log("Foundry operation failed with system error: %s (%d), translated to %"FMT64"d\n",
msg, systemError, err);
- Unicode_Free(msg);
+ free(msg);
#else // linux, other *nix
err = Vix_TranslateErrno(systemError);
diff --git a/open-vm-tools/lib/glibUtils/fileLogger.c b/open-vm-tools/lib/glibUtils/fileLogger.c
index c0c7cc03..80ff74a4 100644
--- a/open-vm-tools/lib/glibUtils/fileLogger.c
+++ b/open-vm-tools/lib/glibUtils/fileLogger.c
@@ -99,6 +99,30 @@ FileLoggerIsValid(FileLogger *logger)
/*
+ * This function is a temporary workaround for a broken glib version
+ * 2.42.2 that is missing g_get_user_name_utf8 export. After glib
+ * is fixed this needs to be removed and call to GlibGetUserName
+ * replaced by g_get_user_name. See bug 1434059 for details.
+ */
+const char* GlibGetUserName()
+{
+#if !defined(_WIN32)
+ return g_get_user_name();
+#else
+ wchar_t buffer[256] = { 0 };
+ DWORD len = ARRAYSIZE(buffer);
+ static char* user_name_utf8 = NULL;
+ if (!user_name_utf8) {
+ if (GetUserNameW(buffer, &len)) {
+ user_name_utf8 = g_utf16_to_utf8(buffer, -1, NULL, NULL, NULL);
+ }
+ }
+ return user_name_utf8;
+#endif
+}
+
+
+/*
*******************************************************************************
* FileLoggerGetPath -- */ /**
*
@@ -135,7 +159,7 @@ FileLoggerGetPath(FileLogger *data,
size_t i;
logpath = g_strdup(data->path);
- vars[1] = (char *) g_get_user_name();
+ vars[1] = (char *) GlibGetUserName();
vars[3] = g_strdup_printf("%u", (unsigned int) getpid());
g_snprintf(indexStr, sizeof indexStr, "%d", index);
diff --git a/open-vm-tools/lib/guestRpc/nicinfo.x b/open-vm-tools/lib/guestRpc/nicinfo.x
index 83f8513c..491fe491 100644
--- a/open-vm-tools/lib/guestRpc/nicinfo.x
+++ b/open-vm-tools/lib/guestRpc/nicinfo.x
@@ -38,7 +38,7 @@ enum NicInfoVersion {
* The IP limit is large enough to hold an IP address (either v4 or v6).
*/
const NICINFO_MAX_IP_LEN = 64;
-const NICINFO_MAX_IPS = 64;
+const NICINFO_MAX_IPS = 2048;
const NICINFO_MAX_NICS = 16;
/* MAC Addresses are "AA:BB:CC:DD:EE:FF" = 18 bytes. */
diff --git a/open-vm-tools/lib/hashMap/hashMap.c b/open-vm-tools/lib/hashMap/hashMap.c
index 287f0889..16a359c6 100644
--- a/open-vm-tools/lib/hashMap/hashMap.c
+++ b/open-vm-tools/lib/hashMap/hashMap.c
@@ -538,6 +538,7 @@ HashMap_Count(struct HashMap *map) // IN
return map->count;
}
+
#ifdef VMX86_SERVER
/*
* ----------------------------------------------------------------------------
@@ -554,6 +555,7 @@ HashMap_Count(struct HashMap *map) // IN
*
* ----------------------------------------------------------------------------
*/
+
uint64
HashMap_Store(struct HashMap *map, // IN
void *h, // IN
@@ -581,12 +583,9 @@ HashMap_Store(struct HashMap *map, // IN
vec.iov_len = sizeof hashMapOnDisk;
numBytes = vec.iov_len;
- aioErr = AIOMgr_Queue(*handle, &vec, 1, OP_WRITE,
- startByteOffset, numBytes, AIOMGR_INVALID_IO_REQUEST_ID, NULL, NULL );
- if (AIOMgr_IsAsync(aioErr)) {
- aioErr = AIOMgr_Sync(*handle);
- }
-
+ aioErr = AIOMgr_Queue(*handle, &vec, 1, OP_WRITE, startByteOffset, numBytes,
+ AIOMGR_INVALID_IO_REQUEST_ID, NULL, NULL);
+ ASSERT(!AIOMgr_IsAsync(aioErr));
if (!AIOMgr_IsSuccess(aioErr)) {
return -1;
}
@@ -598,11 +597,9 @@ HashMap_Store(struct HashMap *map, // IN
vec.iov_len = map->numEntries * map->entrySize;
aioErr = AIOMgr_Queue(*handle, &vec, 1, OP_WRITE,
- startByteOffset + numBytes, vec.iov_len, AIOMGR_INVALID_IO_REQUEST_ID, NULL, NULL );
- if (AIOMgr_IsAsync(aioErr)) {
- aioErr = AIOMgr_Sync(*handle);
- }
-
+ startByteOffset + numBytes, vec.iov_len,
+ AIOMGR_INVALID_IO_REQUEST_ID, NULL, NULL);
+ ASSERT(!AIOMgr_IsAsync(aioErr));
if (!AIOMgr_IsSuccess(aioErr)) {
return -1;
}
@@ -648,11 +645,10 @@ HashMap_Retrieve(void *h, // IN
vec.iov_len = sizeof hashMapOnDisk;
numBytes = vec.iov_len;
if (handle) {
- aioErr = AIOMgr_Queue(*handle, &vec, 1, OP_READ,
- startByteOffset, numBytes, AIOMGR_INVALID_IO_REQUEST_ID, NULL, NULL );
- if (AIOMgr_IsAsync(aioErr)) {
- aioErr = AIOMgr_Sync(*handle);
- }
+ aioErr = AIOMgr_Queue(*handle, &vec, 1, OP_READ, startByteOffset,
+ numBytes, AIOMGR_INVALID_IO_REQUEST_ID, NULL,
+ NULL);
+ ASSERT(!AIOMgr_IsAsync(aioErr));
}
if (!AIOMgr_IsSuccess(aioErr)) {
@@ -686,11 +682,9 @@ HashMap_Retrieve(void *h, // IN
vec.iov_len = map->numEntries * map->entrySize;
ASSERT(handle);
aioErr = AIOMgr_Queue(*handle, &vec, 1, OP_READ,
- startByteOffset + numBytes, vec.iov_len, AIOMGR_INVALID_IO_REQUEST_ID, NULL, NULL );
- if (AIOMgr_IsAsync(aioErr)) {
- aioErr = AIOMgr_Sync(*handle);
- }
-
+ startByteOffset + numBytes, vec.iov_len,
+ AIOMGR_INVALID_IO_REQUEST_ID, NULL, NULL);
+ ASSERT(!AIOMgr_IsAsync(aioErr));
if (!AIOMgr_IsSuccess(aioErr)) {
free(map->entries);
free(map);
diff --git a/open-vm-tools/lib/hgfs/hgfsEscape.c b/open-vm-tools/lib/hgfs/hgfsEscape.c
index ae4230bd..3193f188 100644
--- a/open-vm-tools/lib/hgfs/hgfsEscape.c
+++ b/open-vm-tools/lib/hgfs/hgfsEscape.c
@@ -47,7 +47,7 @@
# else
# include <string.h>
# endif
-# define memmove(s1,s2,n) bcopy(s2,s1,n)
+# define memmove(s1,s2,n) bcopy(s2,s1,n)
#elif defined __APPLE__ && defined KERNEL
# include <string.h>
#elif !defined sun
@@ -824,14 +824,17 @@ HgfsEscape_GetSize(char const *bufIn, // IN: Buffer with unescaped input
*-----------------------------------------------------------------------------
*/
-int
+uint32
HgfsEscape_Undo(char *bufIn, // IN: Characters to be unescaped
uint32 sizeIn) // IN: Number of characters in bufIn
{
- uint32 componentSize = strlen(bufIn) + 1;
+ uint32 componentSize;
uint32 unprocessedSize = sizeIn + 1;
uint32 result = 0;
char *currentComponent = bufIn;
+
+ ASSERT(bufIn != NULL);
+
while (currentComponent != NULL) {
HgfsEscapeUndoComponent(currentComponent, &unprocessedSize);
componentSize = strlen(currentComponent) + 1; // Unescaped size
diff --git a/open-vm-tools/lib/hgfsHelper/hgfsHelperPosix.c b/open-vm-tools/lib/hgfsHelper/hgfsHelperPosix.c
index d1e3b3dd..eae06d6b 100644
--- a/open-vm-tools/lib/hgfsHelper/hgfsHelperPosix.c
+++ b/open-vm-tools/lib/hgfsHelper/hgfsHelperPosix.c
@@ -63,7 +63,7 @@
*/
Bool
-HgfsHlpr_QuerySharesDefaultRootPath(Unicode *hgfsRootPath)
+HgfsHlpr_QuerySharesDefaultRootPath(char **hgfsRootPath)
{
#if defined __FreeBSD__
return FALSE;
@@ -73,7 +73,7 @@ HgfsHlpr_QuerySharesDefaultRootPath(Unicode *hgfsRootPath)
*hgfsRootPath = Unicode_AllocWithUTF8(HGFSHLPR_DEFAULT_MOUNT_PATH);
Debug("%s: HGFS shares root path name \"%s\"\n",
- __FUNCTION__, UTF8(*hgfsRootPath));
+ __FUNCTION__, *hgfsRootPath);
return TRUE;
#endif
@@ -98,7 +98,7 @@ HgfsHlpr_QuerySharesDefaultRootPath(Unicode *hgfsRootPath)
*/
void
-HgfsHlpr_FreeSharesRootPath(Unicode hgfsRootPath)
+HgfsHlpr_FreeSharesRootPath(char *hgfsRootPath)
{
- Unicode_Free(hgfsRootPath);
+ free(hgfsRootPath);
}
diff --git a/open-vm-tools/lib/hgfsServer/hgfsServer.c b/open-vm-tools/lib/hgfsServer/hgfsServer.c
index b3dc1cfa..0939655b 100644
--- a/open-vm-tools/lib/hgfsServer/hgfsServer.c
+++ b/open-vm-tools/lib/hgfsServer/hgfsServer.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
+ * Copyright (C) 1998,2014-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -47,7 +47,6 @@
#include "hgfsServerParameters.h"
#include "hgfsServerOplock.h"
#include "hgfsDirNotify.h"
-#include "hgfsTransport.h"
#include "userlock.h"
#include "poll.h"
#include "mutexRankLib.h"
@@ -200,7 +199,7 @@ static Atomic_uint32 gHgfsAsyncCounter = {0};
static MXUserExclLock *gHgfsAsyncLock;
static MXUserCondVar *gHgfsAsyncVar;
-static HgfsServerStateLogger *hgfsMgrData = NULL;
+static HgfsServerMgrCallbacks *gHgfsMgrData = NULL;
/*
* Session usage and locking.
@@ -237,18 +236,24 @@ static void HgfsServerSessionInvalidateObjects(void *clientData,
DblLnkLst_Links *shares);
static uint32 HgfsServerSessionInvalidateInactiveSessions(void *clientData);
static void HgfsServerSessionSendComplete(HgfsPacket *packet, void *clientData);
+static HgfsSharedFolderHandle HgfsServerRegisterShare(const char *shareName,
+ const char *sharePath,
+ Bool addFolder);
/*
* Callback table passed to transport and any channels.
*/
-HgfsServerSessionCallbacks hgfsServerSessionCBTable = {
- HgfsServerSessionConnect,
- HgfsServerSessionDisconnect,
- HgfsServerSessionClose,
- HgfsServerSessionReceive,
- HgfsServerSessionInvalidateObjects,
- HgfsServerSessionInvalidateInactiveSessions,
- HgfsServerSessionSendComplete,
+HgfsServerCallbacks gHgfsServerCBTable = {
+ {
+ HgfsServerSessionConnect,
+ HgfsServerSessionDisconnect,
+ HgfsServerSessionClose,
+ HgfsServerSessionReceive,
+ HgfsServerSessionInvalidateObjects,
+ HgfsServerSessionInvalidateInactiveSessions,
+ HgfsServerSessionSendComplete,
+ },
+ HgfsServerRegisterShare,
};
/* Lock that protects shared folders list. */
@@ -562,17 +567,7 @@ HgfsServerGetHandleCounter(void)
static uint32
HgfsServerGetNextHandleCounter(void)
{
- uint32 count = Atomic_ReadInc32(&hgfsHandleCounter);
- /*
- * Call server manager for logging state updates.
- * XXX - This will have to be reworked when the server is
- * more concurrent than with the current access.
- */
- if (hgfsMgrData != NULL &&
- hgfsMgrData->logger != NULL) {
- hgfsMgrData->logger(hgfsMgrData->loggerData, count + 1);
- }
- return count;
+ return Atomic_ReadInc32(&hgfsHandleCounter);
}
@@ -1628,17 +1623,23 @@ HgfsRemoveFileNode(HgfsFileNode *node, // IN: file node
if (node->shareName) {
free(node->shareName);
+ node->shareName = NULL;
}
- node->shareName = NULL;
if (node->utf8Name) {
free(node->utf8Name);
+ node->utf8Name = NULL;
}
- node->utf8Name = NULL;
+
node->state = FILENODE_STATE_UNUSED;
ASSERT(node->fileCtx == NULL);
node->fileCtx = NULL;
+ if (node->shareInfo.rootDir) {
+ free((void*)node->shareInfo.rootDir);
+ node->shareInfo.rootDir = NULL;
+ }
+
/* Prepend at the beginning of the list */
DblLnkLst_LinkFirst(&session->nodeFreeList, &node->links);
}
@@ -3089,6 +3090,46 @@ exit:
/*
*-----------------------------------------------------------------------------
*
+ * HgfsServerGetRequestHeaderSize --
+ *
+ * Takes the Hgfs request input and finds the size of the header component.
+ *
+ * Results:
+ * Size of the HGFS protocol header used by this request and reply.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static HgfsInternalStatus
+HgfsServerGetRequestHeaderSize(HgfsInputParam *input) // IN: parameters
+{
+ size_t headerSize;
+
+ /*
+ * If the HGFS request is session enabled we must have the new header.
+ * Otherwise, starting from HGFS V3 the header is not included in the
+ * request itself, so we must return the size of the separate HgfsReply
+ * structure. Prior to V3 (so V1 and V2) there was no separate header
+ * from the request result structure so a zero size is returned for these
+ * operations.
+ */
+ if (input->sessionEnabled) {
+ headerSize = sizeof (HgfsHeader);
+ } else if (input->op >= HGFS_OP_OPEN_V3) {
+ headerSize = sizeof (HgfsReply);
+ } else {
+ headerSize = 0;
+ }
+ return headerSize;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* HgfsServerCompleteRequest --
*
* Performs all necessary action which needed for completing HGFS request:
@@ -3113,6 +3154,7 @@ HgfsServerCompleteRequest(HgfsInternalStatus status, // IN: Status of the requ
void *reply;
size_t replySize;
size_t replyTotalSize;
+ size_t replyHeaderSize;
uint64 replySessionId;
if (HGFS_ERROR_SUCCESS == status) {
@@ -3123,18 +3165,20 @@ HgfsServerCompleteRequest(HgfsInternalStatus status, // IN: Status of the requ
replySessionId = (NULL != input->session) ? input->session->sessionId
: HGFS_INVALID_SESSION_ID;
+ replyHeaderSize = HgfsServerGetRequestHeaderSize(input);
- if (input->sessionEnabled) {
- replySize = sizeof (HgfsHeader) + replyPayloadSize;
+ if (replyHeaderSize != 0) {
+ replySize = replyHeaderSize + replyPayloadSize;
} else {
/*
- * Starting from HGFS V3 header is not included in the payload size.
+ * For pre-V3 header is included in the payload size.
+ * If we want to send just an error result then HgfsReply
+ * only size is required.
+ *
+ * XXX - all callers should be verified that the reply payload
+ * size for V1 and V2 should be correct (mininum HgfsReply size).
*/
- if (input->op < HGFS_OP_OPEN_V3) {
- replySize = MAX(replyPayloadSize, sizeof (HgfsReply));
- } else {
- replySize = sizeof (HgfsReply) + replyPayloadSize;
- }
+ replySize = MAX(replyPayloadSize, sizeof (HgfsReply));
}
reply = HSPU_GetReplyPacket(input->packet,
@@ -3534,7 +3578,7 @@ HgfsServerCleanupDeletedFolders(void)
/*
*-----------------------------------------------------------------------------
*
- * HgfsServer_RegisterSharedFolder --
+ * HgfsServerRegisterShare --
*
* This is a callback function which is invoked by hgfsServerManagement
* for every shared folder when something changed in shared folders
@@ -3559,10 +3603,10 @@ HgfsServerCleanupDeletedFolders(void)
*-----------------------------------------------------------------------------
*/
-HgfsSharedFolderHandle
-HgfsServer_RegisterSharedFolder(const char *shareName, // IN: shared folder name
- const char *sharePath, // IN: shared folder path
- Bool addFolder) // IN: add or remove folder
+static HgfsSharedFolderHandle
+HgfsServerRegisterShare(const char *shareName, // IN: shared folder name
+ const char *sharePath, // IN: shared folder path
+ Bool addFolder) // IN: add or remove folder
{
DblLnkLst_Links *link, *nextElem;
HgfsSharedFolderHandle result = HGFS_INVALID_FOLDER_HANDLE;
@@ -3729,16 +3773,16 @@ HgfsServerGetShareName(HgfsSharedFolderHandle sharedFolder, // IN: Notify handle
*/
Bool
-HgfsServer_InitState(HgfsServerSessionCallbacks **callbackTable, // IN/OUT: our callbacks
+HgfsServer_InitState(HgfsServerCallbacks **callbackTable, // IN/OUT: our callbacks
HgfsServerConfig *serverCfgData, // IN: configurable settings
- HgfsServerStateLogger *serverMgrData) // IN: mgr callback
+ HgfsServerMgrCallbacks *serverMgrData) // IN: mgr callback
{
Bool result = TRUE;
ASSERT(callbackTable);
/* Save any server manager data for logging state updates.*/
- hgfsMgrData = serverMgrData;
+ gHgfsMgrData = serverMgrData;
if (NULL != serverCfgData) {
gHgfsCfgSettings = *serverCfgData;
@@ -3780,7 +3824,7 @@ HgfsServer_InitState(HgfsServerSessionCallbacks **callbackTable, // IN/OUT: our
}
if (result) {
- *callbackTable = &hgfsServerSessionCBTable;
+ *callbackTable = &gHgfsServerCBTable;
if (0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_NOTIFY_ENABLED)) {
gHgfsDirNotifyActive = HgfsNotify_Init() == HGFS_STATUS_SUCCESS;
@@ -3851,6 +3895,10 @@ HgfsServer_ExitState(void)
}
HgfsPlatformDestroy();
+ /*
+ * Reset the server manager callbacks.
+ */
+ gHgfsMgrData = NULL;
}
@@ -3918,6 +3966,102 @@ HgfsServerSetSessionCapability(HgfsOp op, // IN: operation code
/*
*-----------------------------------------------------------------------------
*
+ * HgfsServerResEnumInit --
+ *
+ * Initialize an enumeration of all exisitng resources.
+ *
+ * Results:
+ * The enumeration state object.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void *
+HgfsServerResEnumInit(void)
+{
+ void *enumState = NULL;
+
+ if (gHgfsMgrData != NULL &&
+ gHgfsMgrData->enumResources.init != NULL) {
+ enumState = gHgfsMgrData->enumResources.init();
+ }
+
+ return enumState;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerResEnumGet --
+ *
+ * Enumerates the next resource associated with the enumeration state.
+ *
+ * Results:
+ * TRUE on success and .
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+HgfsServerResEnumGet(void *enumState, // IN/OUT: enumeration state
+ char const **enumResName, // OUT: enumerated resource name
+ size_t *enumResNameLen, // OUT: enumerated resource name len
+ Bool *enumResDone) // OUT: enumerated resources done
+{
+ Bool success = FALSE;
+
+ if (gHgfsMgrData != NULL &&
+ gHgfsMgrData->enumResources.get != NULL) {
+ success = gHgfsMgrData->enumResources.get(enumState,
+ enumResName,
+ enumResNameLen,
+ enumResDone);
+ }
+
+ return success;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerResEnumExit --
+ *
+ * Exit the enumeration of all existing resources.
+ *
+ * Results:
+ * TRUE on success, FALSE otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+HgfsServerResEnumExit(void *enumState) // IN/OUT: enumeration state
+{
+ Bool success = FALSE;
+
+ if (gHgfsMgrData != NULL &&
+ gHgfsMgrData->enumResources.exit != NULL) {
+ success = gHgfsMgrData->enumResources.exit(enumState);
+ }
+
+ return success;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* HgfsServerEnumerateSharedFolders --
*
* Enumerates all exisitng shared folders and registers shared folders with
@@ -3939,7 +4083,7 @@ HgfsServerEnumerateSharedFolders(void)
Bool success = FALSE;
LOG(8, ("%s: entered\n", __FUNCTION__));
- state = HgfsServerPolicy_GetSharesInit();
+ state = HgfsServerResEnumInit();
if (NULL != state) {
Bool done;
@@ -3947,7 +4091,7 @@ HgfsServerEnumerateSharedFolders(void)
char const *shareName;
size_t len;
- success = HgfsServerPolicy_GetShares(state, &shareName, &len, &done);
+ success = HgfsServerResEnumGet(state, &shareName, &len, &done);
if (success && !done) {
HgfsSharedFolderHandle handle;
char const *sharePath;
@@ -3959,15 +4103,14 @@ HgfsServerEnumerateSharedFolders(void)
&sharePathLen, &sharePath);
if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
LOG(8, ("%s: registering share %s path %s\n", __FUNCTION__, shareName, sharePath));
- handle = HgfsServer_RegisterSharedFolder(shareName, sharePath,
- TRUE);
+ handle = HgfsServerRegisterShare(shareName, sharePath, TRUE);
success = handle != HGFS_INVALID_FOLDER_HANDLE;
LOG(8, ("%s: registering share %s hnd %#x\n", __FUNCTION__, shareName, handle));
}
}
} while (!done && success);
- HgfsServerPolicy_GetSharesCleanup(state);
+ HgfsServerResEnumExit(state);
}
LOG(8, ("%s: exit %d\n", __FUNCTION__, success));
return success;
@@ -4470,7 +4613,9 @@ HgfsServerSessionSendComplete(HgfsPacket *packet, // IN/OUT: Hgfs packet
HSPU_PutReplyPacket(packet, transportSession->channelCbTable);
HSPU_PutDataPacketBuf(packet, transportSession->channelCbTable);
} else {
- free(packet->metaPacket);
+ if (packet->metaPacketIsAllocated) {
+ free(packet->metaPacket);
+ }
free(packet);
}
}
@@ -5381,12 +5526,12 @@ HgfsServerSearchRealDir(char const *baseDir, // IN: Directory to search
*/
HgfsInternalStatus
-HgfsServerSearchVirtualDir(HgfsGetNameFunc *getName, // IN: Name enumerator
- HgfsInitFunc *initName, // IN: Init function
- HgfsCleanupFunc *cleanupName, // IN: Cleanup function
- DirectorySearchType type, // IN: Kind of search
- HgfsSessionInfo *session, // IN: Session info
- HgfsHandle *handle) // OUT: Search handle
+HgfsServerSearchVirtualDir(HgfsServerResEnumGetFunc getName, // IN: Name enumerator
+ HgfsServerResEnumInitFunc initName, // IN: Init function
+ HgfsServerResEnumExitFunc cleanupName, // IN: Cleanup function
+ DirectorySearchType type, // IN: Kind of search
+ HgfsSessionInfo *session, // IN: Session info
+ HgfsHandle *handle) // OUT: Search handle
{
HgfsInternalStatus status = 0;
HgfsSearch *search = NULL;
@@ -5447,11 +5592,11 @@ HgfsServerSearchVirtualDir(HgfsGetNameFunc *getName, // IN: Name enumerator
*/
HgfsInternalStatus
-HgfsServerRestartSearchVirtualDir(HgfsGetNameFunc *getName, // IN: Name enumerator
- HgfsInitFunc *initName, // IN: Init function
- HgfsCleanupFunc *cleanupName, // IN: Cleanup function
- HgfsSessionInfo *session, // IN: Session info
- HgfsHandle searchHandle) // IN: search to restart
+HgfsServerRestartSearchVirtualDir(HgfsServerResEnumGetFunc getName, // IN: Name enumerator
+ HgfsServerResEnumInitFunc initName, // IN: Init function
+ HgfsServerResEnumExitFunc cleanupName, // IN: Cleanup function
+ HgfsSessionInfo *session, // IN: Session info
+ HgfsHandle searchHandle) // IN: search to restart
{
HgfsInternalStatus status = 0;
HgfsSearch *vdirSearch;
@@ -5790,6 +5935,10 @@ HgfsAllocInitReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
void *replyHeader;
void *replyData;
+ /*
+ * XXX - this should be modified to use the common HgfsServerGetRequestHeaderSize
+ * so that all requests and replies are handled consistently.
+ */
if (HGFS_OP_NEW_HEADER == request->op) {
headerSize = sizeof(HgfsHeader);
} else if (request->op < HGFS_OP_CREATE_SESSION_V4 &&
@@ -5818,6 +5967,102 @@ HgfsAllocInitReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
/*
*-----------------------------------------------------------------------------
*
+ * HgfsServerValidateRead --
+ *
+ * Validate a Read request's arguments.
+ *
+ * Note, the readOffset is ignored here but is checked in the platform specific
+ * read handler.
+ *
+ * Results:
+ * HGFS_ERROR_SUCCESS on success.
+ * HGFS error code on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static HgfsInternalStatus
+HgfsServerValidateRead(HgfsInputParam *input, // IN: Input params
+ HgfsHandle readHandle, // IN: read Handle
+ uint32 readSize, // IN: size to read
+ uint64 readOffset, // IN: offset to read unused
+ fileDesc *readfd, // OUT: read file descriptor
+ size_t *readReplySize, // OUT: read reply size
+ size_t *readDataSize) // OUT: read data size
+{
+ HgfsInternalStatus status = HGFS_ERROR_SUCCESS;
+ size_t replyReadHeaderSize;
+ size_t replyReadResultSize = 0;
+ size_t replyReadResultDataSize = 0;
+ size_t replyReadDataSize = 0;
+ fileDesc readFileDesc = 0;
+ Bool useMappedBuffer;
+
+ useMappedBuffer = (input->transportSession->channelCbTable->getWriteVa != NULL);
+ replyReadHeaderSize = HgfsServerGetRequestHeaderSize(input);
+ switch (input->op) {
+ case HGFS_OP_READ_FAST_V4:
+ /* Data is packed into a separate buffer from the read results. */
+ replyReadResultSize = sizeof (HgfsReplyReadV3);
+ replyReadResultDataSize = 0;
+ replyReadDataSize = readSize;
+ break;
+ case HGFS_OP_READ_V3:
+ /* Data is packed as a part of the read results. */
+ replyReadResultSize = sizeof (HgfsReplyReadV3);
+ replyReadResultDataSize = readSize;
+ replyReadDataSize = 0;
+ break;
+ case HGFS_OP_READ:
+ /* Data is packed as a part of the read results. */
+ replyReadResultSize = sizeof (HgfsReplyRead);
+ replyReadResultDataSize = readSize;
+ replyReadDataSize = 0;
+ break;
+ default:
+ status = HGFS_ERROR_PROTOCOL;
+ LOG(4, ("%s: Unsupported protocol version passed %d -> PROTOCOL_ERROR.\n",
+ __FUNCTION__, input->op));
+ NOT_IMPLEMENTED();
+ goto exit;
+ }
+
+ if (!HSPU_ValidateDataPacketSize(input->packet, replyReadDataSize) ||
+ !HSPU_ValidateReplyPacketSize(input->packet,
+ replyReadHeaderSize,
+ replyReadResultSize,
+ replyReadResultDataSize,
+ useMappedBuffer)) {
+ status = HGFS_ERROR_INVALID_PARAMETER;
+ LOG(4, ("%s: Error: arg validation read size -> %d.\n",
+ __FUNCTION__, status));
+ goto exit;
+ }
+
+ /* Validate the file handle by retrieving it possibly from the cache. */
+ status = HgfsPlatformGetFd(readHandle, input->session, FALSE, &readFileDesc);
+ if (status != HGFS_ERROR_SUCCESS) {
+ LOG(4, ("%s: Error: arg validation handle -> %d.\n",
+ __FUNCTION__, status));
+ goto exit;
+ }
+
+exit:
+ *readDataSize = replyReadDataSize;
+ *readReplySize = replyReadResultSize + replyReadResultDataSize;
+ *readfd = readFileDesc;
+ LOG(4, ("%s: arg validation check return (%"FMTSZ"u) %d.\n",
+ __FUNCTION__, replyReadDataSize, status));
+ return status;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* HgfsServerRead --
*
* Handle a Read request.
@@ -5837,9 +6082,13 @@ HgfsServerRead(HgfsInputParam *input) // IN: Input params
{
HgfsInternalStatus status;
HgfsHandle file;
+ fileDesc readFd;
uint64 offset;
uint32 requiredSize;
size_t replyPayloadSize = 0;
+ size_t replyReadSize = 0;
+ size_t replyReadDataSize = 0;
+ void *replyRead;
HGFS_ASSERT_INPUT(input);
@@ -5847,61 +6096,87 @@ HgfsServerRead(HgfsInputParam *input) // IN: Input params
&offset, &requiredSize)) {
LOG(4, ("%s: Failed to unpack a valid packet -> PROTOCOL_ERROR.\n", __FUNCTION__));
status = HGFS_ERROR_PROTOCOL;
- } else {
- switch(input->op) {
- case HGFS_OP_READ_FAST_V4:
- case HGFS_OP_READ_V3: {
- HgfsReplyReadV3 *reply;
- void *payload;
- uint32 inlineDataSize =
- (HGFS_OP_READ_FAST_V4 == input->op) ? 0 : requiredSize;
-
- reply = HgfsAllocInitReply(input->packet, input->request,
- sizeof *reply + inlineDataSize, input->session);
- if (HGFS_OP_READ_V3 == input->op) {
- payload = &reply->payload[0];
- } else {
- payload = HSPU_GetDataPacketBuf(input->packet, BUF_WRITEABLE,
- input->transportSession->channelCbTable);
- }
- if (payload) {
- status = HgfsPlatformReadFile(file, input->session, offset,
- requiredSize, payload,
- &reply->actualSize);
- if (HGFS_ERROR_SUCCESS == status) {
- reply->reserved = 0;
- replyPayloadSize = sizeof *reply +
- ((inlineDataSize > 0) ? reply->actualSize : 0);
- }
- } else {
- status = HGFS_ERROR_PROTOCOL;
- LOG(4, ("%s: V3/V4 Failed to get payload -> PROTOCOL_ERROR.\n", __FUNCTION__));
- }
- break;
- }
- case HGFS_OP_READ: {
- HgfsReplyRead *reply;
+ goto exit;
+ }
+
+ /*
+ * Validate the read arguments with the data and reply buffers to ensure
+ * there isn't a malformed request or we read more data than the buffer can
+ * hold.
+ */
+ status = HgfsServerValidateRead(input,
+ file,
+ requiredSize,
+ offset,
+ &readFd,
+ &replyReadSize,
+ &replyReadDataSize);
+ if (status != HGFS_ERROR_SUCCESS) {
+ LOG(4, ("%s: Error: validate args %u.\n", __FUNCTION__, status));
+ goto exit;
+ }
- reply = HgfsAllocInitReply(input->packet, input->request,
- sizeof *reply + requiredSize, input->session);
+ replyRead = HgfsAllocInitReply(input->packet,
+ input->request,
+ replyReadSize,
+ input->session);
- status = HgfsPlatformReadFile(file, input->session, offset, requiredSize,
- reply->payload, &reply->actualSize);
+ switch (input->op) {
+ case HGFS_OP_READ_FAST_V4:
+ case HGFS_OP_READ_V3: {
+ HgfsReplyReadV3 *reply = replyRead;
+ void *payload;
+ Bool readUseDataBuffer = replyReadDataSize != 0;
+
+ /*
+ * The read data size holds the size of the data to read which will be read
+ * into the separate data packet buffer. Zero indicates data is read into the
+ * same buffer as the reply arguments.
+ */
+ if (readUseDataBuffer) {
+ payload = HSPU_GetDataPacketBuf(input->packet, BUF_WRITEABLE,
+ input->transportSession->channelCbTable);
+ } else {
+ payload = &reply->payload[0];
+ }
+ if (payload) {
+ status = HgfsPlatformReadFile(readFd, input->session, offset,
+ requiredSize, payload,
+ &reply->actualSize);
if (HGFS_ERROR_SUCCESS == status) {
- replyPayloadSize = sizeof *reply + reply->actualSize;
- } else {
- LOG(4, ("%s: V1 Failed to read-> %d.\n", __FUNCTION__, status));
+ reply->reserved = 0;
+ replyPayloadSize = sizeof *reply;
+
+ if (readUseDataBuffer) {
+ HSPU_SetDataPacketSize(input->packet, reply->actualSize);
+ } else {
+ replyPayloadSize += reply->actualSize;
+ }
}
- break;
+ } else {
+ status = HGFS_ERROR_PROTOCOL;
+ LOG(4, ("%s: V3/V4 Failed to get payload -> PROTOCOL_ERROR.\n", __FUNCTION__));
}
- default:
- NOT_IMPLEMENTED();
- status = HGFS_ERROR_PROTOCOL;
- LOG(4, ("%s: Unsupported protocol version passed %d -> PROTOCOL_ERROR.\n",
- __FUNCTION__, input->op));
+ break;
}
+ case HGFS_OP_READ: {
+ HgfsReplyRead *reply = replyRead;
+
+ status = HgfsPlatformReadFile(readFd, input->session, offset, requiredSize,
+ reply->payload, &reply->actualSize);
+ if (HGFS_ERROR_SUCCESS == status) {
+ replyPayloadSize = sizeof *reply + reply->actualSize;
+ } else {
+ LOG(4, ("%s: V1 Failed to read-> %d.\n", __FUNCTION__, status));
+ }
+ break;
+ }
+ default:
+ NOT_REACHED();
+ break;
}
+exit:
HgfsServerCompleteRequest(status, replyPayloadSize, input);
}
@@ -5946,6 +6221,7 @@ HgfsServerWrite(HgfsInputParam *input) // IN: Input params
if (NULL == dataToWrite) {
/* No inline data to write, get it from the transport shared memory. */
+ HSPU_SetDataPacketSize(input->packet, numberBytesToWrite);
dataToWrite = HSPU_GetDataPacketBuf(input->packet, BUF_READABLE,
input->transportSession->channelCbTable);
if (NULL == dataToWrite) {
@@ -6312,7 +6588,7 @@ HgfsServerSearchOpen(HgfsInputParam *input) // IN: Input params
HgfsInternalStatus status;
size_t replyPayloadSize = 0;
const char *dirName;
- uint32 dirNameLength;
+ size_t dirNameLength;
uint32 caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
HgfsHandle search;
HgfsNameStatus nameStatus;
@@ -8043,8 +8319,8 @@ HgfsServerSearchRead(HgfsInputParam *input) // IN: Input params
/* Get the config options. */
if (search.utf8ShareNameLen != 0) {
nameStatus = HgfsServerPolicy_GetShareOptions(search.utf8ShareName,
- search.utf8ShareNameLen,
- &configOptions);
+ search.utf8ShareNameLen,
+ &configOptions);
if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__,
search.utf8ShareName));
@@ -8077,8 +8353,8 @@ HgfsServerSearchRead(HgfsInputParam *input) // IN: Input params
* else.
*/
status = HgfsPlatformRestartSearchDir(hgfsSearchHandle,
- input->session,
- search.type);
+ input->session,
+ search.type);
}
}
@@ -8095,6 +8371,9 @@ HgfsServerSearchRead(HgfsInputParam *input) // IN: Input params
if (HGFS_ERROR_SUCCESS == status) {
replyPayloadSize = replyInfoSize +
((inlineDataSize == 0) ? 0 : replyDirentSize);
+ if (0 == inlineDataSize) {
+ HSPU_SetDataPacketSize(input->packet, replyDirentSize);
+ }
}
free(search.utf8Dir);
@@ -8393,13 +8672,20 @@ HgfsServerDirWatchEvent(HgfsSharedFolderHandle sharedFolder, // IN: shared folde
sizeNeeded = HgfsPackCalculateNotificationSize(shareName, fileName);
- packetHeader = Util_SafeCalloc(1, sizeNeeded);
- packet = Util_SafeCalloc(1, sizeof *packet);
- packet->state &= ~HGFS_STATE_CLIENT_REQUEST;
+ /*
+ * Use a single buffer zero'd out, as the packet and metapacket have the same
+ * lifespan which is ended at the send complete callback (HgfsServerSessionSendComplete).
+ */
+ packet = Util_SafeCalloc(1, sizeof *packet + sizeNeeded);
+ packetHeader = (HgfsHeader *)((char *)packet + sizeof *packet);
+ /*
+ * The buffer is zero'd out, so no need to set the following explicitly:
+ * packet->metaPacketIsAllocated = FALSE;
+ * packet->state &= ~HGFS_STATE_CLIENT_REQUEST;
+ */
packet->metaPacketSize = sizeNeeded;
packet->metaPacketDataSize = packet->metaPacketSize;
packet->metaPacket = packetHeader;
- packet->dataPacketIsAllocated = TRUE;
notifyFlags = 0;
if (mask & HGFS_NOTIFY_EVENTS_DROPPED) {
notifyFlags |= HGFS_NOTIFY_FLAG_OVERFLOW;
@@ -8418,7 +8704,6 @@ HgfsServerDirWatchEvent(HgfsSharedFolderHandle sharedFolder, // IN: shared folde
/* The transport will call the server send complete callback to release the packets. */
packet = NULL;
- packetHeader = NULL;
LOG(4, ("%s: Sent notify for: %u index: %"FMT64"u file name %s mask %x\n",
__FUNCTION__, sharedFolder, subscriber, fileName, mask));
@@ -8430,9 +8715,6 @@ exit:
if (packet) {
free(packet);
}
- if (packetHeader) {
- free(packetHeader);
- }
}
diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerInt.h b/open-vm-tools/lib/hgfsServer/hgfsServerInt.h
index 5785756e..ef4926bb 100644
--- a/open-vm-tools/lib/hgfsServer/hgfsServerInt.h
+++ b/open-vm-tools/lib/hgfsServer/hgfsServerInt.h
@@ -504,6 +504,18 @@ Bool
HgfsServerIsSharedFolderOnly(char const *in, // IN: CP filename to check
size_t inSize); // IN: Size of name in
+void *
+HgfsServerResEnumInit(void);
+
+Bool
+HgfsServerResEnumGet(void *enumState,
+ char const **enumResName,
+ size_t *enumResNameLen,
+ Bool *enumResDone);
+
+Bool
+HgfsServerResEnumExit(void *enumState);
+
HgfsInternalStatus
HgfsServerGetDirEntry(HgfsHandle handle, // IN: Handle to search
HgfsSessionInfo *session, // IN: Session info
@@ -520,19 +532,19 @@ HgfsServerSearchRealDir(char const *baseDir, // IN: Directory to search
HgfsHandle *handle); // OUT: Search handle
HgfsInternalStatus
-HgfsServerSearchVirtualDir(HgfsGetNameFunc *getName, // IN: Name enumerator
- HgfsInitFunc *initName, // IN: Init function
- HgfsCleanupFunc *cleanupName, // IN: Cleanup function
- DirectorySearchType type, // IN: Kind of search
- HgfsSessionInfo *session, // IN: Session info
- HgfsHandle *handle); // OUT: Search handle
+HgfsServerSearchVirtualDir(HgfsServerResEnumGetFunc getName, // IN: Name enumerator
+ HgfsServerResEnumInitFunc initName, // IN: Init function
+ HgfsServerResEnumExitFunc cleanupName, // IN: Cleanup function
+ DirectorySearchType type, // IN: Kind of search
+ HgfsSessionInfo *session, // IN: Session info
+ HgfsHandle *handle); // OUT: Search handle
HgfsInternalStatus
-HgfsServerRestartSearchVirtualDir(HgfsGetNameFunc *getName, // IN: Name enumerator
- HgfsInitFunc *initName, // IN: Init function
- HgfsCleanupFunc *cleanupName, // IN: Cleanup function
- HgfsSessionInfo *session, // IN: Session info
- HgfsHandle searchHandle); // IN: search to restart
+HgfsServerRestartSearchVirtualDir(HgfsServerResEnumGetFunc getName, // IN: Name enumerator
+ HgfsServerResEnumInitFunc initName, // IN: Init function
+ HgfsServerResEnumExitFunc cleanupName, // IN: Cleanup function
+ HgfsSessionInfo *session, // IN: Session info
+ HgfsHandle searchHandle); // IN: search to restart
void *
@@ -703,16 +715,16 @@ HgfsPlatformScandir(char const *baseDir, // IN: Directory to search
struct DirectoryEntry ***dents, // OUT: Array of DirectoryEntrys
int *numDents); // OUT: Number of DirectoryEntrys
HgfsInternalStatus
-HgfsPlatformScanvdir(HgfsGetNameFunc enumNamesGet, // IN: Function to get name
- HgfsInitFunc enumNamesInit, // IN: Setup function
- HgfsCleanupFunc enumNamesExit, // IN: Cleanup function
- DirectorySearchType type, // IN: Kind of search
- struct DirectoryEntry ***dents, // OUT: Array of DirectoryEntrys
- uint32 *numDents); // OUT: total number of directory entrys
+HgfsPlatformScanvdir(HgfsServerResEnumGetFunc enumNamesGet, // IN: Function to get name
+ HgfsServerResEnumInitFunc enumNamesInit, // IN: Setup function
+ HgfsServerResEnumExitFunc enumNamesExit, // IN: Cleanup function
+ DirectorySearchType type, // IN: Kind of search
+ struct DirectoryEntry ***dents, // OUT: Array of DirectoryEntrys
+ uint32 *numDents); // OUT: total number of directory entrys
HgfsInternalStatus
HgfsPlatformSearchDir(HgfsNameStatus nameStatus, // IN: name status
const char *dirName, // IN: relative directory name
- uint32 dirNameLength, // IN: length of dirName
+ size_t dirNameLength, // IN: length of dirName
uint32 caseFlags, // IN: case flags
HgfsShareInfo *shareInfo, // IN: sharfed folder information
char *baseDir, // IN: name of the shared directory
@@ -729,7 +741,7 @@ HgfsPlatformDirDumpDents(HgfsSearch *search); // IN: search
#endif
HgfsInternalStatus
-HgfsPlatformReadFile(HgfsHandle file, // IN: Hgfs file handle
+HgfsPlatformReadFile(fileDesc readFile, // IN: file descriptor
HgfsSessionInfo *session, // IN: session info
uint64 offset, // IN: file offset to read from
uint32 requiredSize, // IN: length of data to read
@@ -824,12 +836,20 @@ HSPU_GetMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
size_t *metaPacketSize, // OUT: Size of metaPacket
HgfsServerChannelCallbacks *chanCb); // IN: Channel callbacks
+Bool
+HSPU_ValidateDataPacketSize(HgfsPacket *packet, // IN: Hgfs Packet
+ size_t dataSize); // IN: data size
+
void *
HSPU_GetDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
MappingType mappingType, // IN: Readable/ Writeable ?
HgfsServerChannelCallbacks *chanCb); // IN: Channel callbacks
void
+HSPU_SetDataPacketSize(HgfsPacket *packet, // IN/OUT: Hgfs Packet
+ size_t dataSize); // IN: data size
+
+void
HSPU_PutDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
HgfsServerChannelCallbacks *chanCb); // IN: Channel callbacks
@@ -837,6 +857,13 @@ void
HSPU_PutMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
HgfsServerChannelCallbacks *chanCb); // IN: Channel callbacks
+Bool
+HSPU_ValidateReplyPacketSize(HgfsPacket *packet, // IN: Hgfs Packet
+ size_t replyHeaderSize, // IN: reply header size
+ size_t replyResultSize, // IN: reply result size
+ size_t replyResultDataSize, // IN: reply result data size
+ Bool useMappedMetaPacket); // IN: using meta buffer
+
void *
HSPU_GetReplyPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
HgfsServerChannelCallbacks *chanCb, // IN: Channel callbacks
diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerLinux.c b/open-vm-tools/lib/hgfsServer/hgfsServerLinux.c
index 9bcf3bd4..b874ce9b 100644
--- a/open-vm-tools/lib/hgfsServer/hgfsServerLinux.c
+++ b/open-vm-tools/lib/hgfsServer/hgfsServerLinux.c
@@ -43,6 +43,7 @@
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h>
+#include <sys/resource.h> // for getrlimit
#if defined(__FreeBSD__)
# include <sys/param.h>
@@ -376,7 +377,10 @@ static HgfsInternalStatus HgfsEffectivePermissions(char *fileName,
uint32 *permissions);
static uint64 HgfsGetCreationTime(const struct stat *stats);
-
+#if !defined(sun)
+static HgfsInternalStatus HgfsWriteCheckIORange(off_t offset,
+ uint32 bytesToWrite);
+#endif
/*
*-----------------------------------------------------------------------------
@@ -867,7 +871,7 @@ HgfsPlatformGetFd(HgfsHandle hgfsHandle, // IN: HGFS file handle
/*
*-----------------------------------------------------------------------------
*
- * HgfsValidateOpen --
+ * HgfsPlatformValidateOpen --
*
* Verify that the file with the given local name exists in the
* local filesystem by trying to open the file with the requested
@@ -894,7 +898,6 @@ HgfsPlatformValidateOpen(HgfsFileOpenInfo *openInfo, // IN: Open info struct
{
struct stat fileStat;
int fd;
- int error;
int openMode = 0, openFlags = 0;
mode_t openPerms;
HgfsLockType serverLock;
@@ -928,7 +931,7 @@ HgfsPlatformValidateOpen(HgfsFileOpenInfo *openInfo, // IN: Open info struct
* a file requires a valid mode, it's highly unlikely that we'll ever
* be creating a file without owner permissions.
*/
- openPerms = ~ALLPERMS;
+ openPerms = 0;
openPerms |= openInfo->mask & HGFS_OPEN_VALID_SPECIAL_PERMS ?
openInfo->specialPerms << 9 : 0;
openPerms |= openInfo->mask & HGFS_OPEN_VALID_OWNER_PERMS ?
@@ -986,6 +989,9 @@ HgfsPlatformValidateOpen(HgfsFileOpenInfo *openInfo, // IN: Open info struct
}
}
if (status != 0) {
+ LOG(4, ("%s: Error: Unwritable share mode %u flags %u file \"%s\": %d %s\n",
+ __FUNCTION__, openMode, openFlags, openInfo->utf8Name,
+ status, strerror(status)));
goto exit;
}
}
@@ -1005,6 +1011,8 @@ HgfsPlatformValidateOpen(HgfsFileOpenInfo *openInfo, // IN: Open info struct
status = EACCES;
}
if (status != 0) {
+ LOG(4, ("%s: Error: Unreadable share flags %u file \"%s\": %d %s\n",
+ __FUNCTION__, openFlags, openInfo->utf8Name, status, strerror(status)));
goto exit;
}
}
@@ -1030,23 +1038,29 @@ HgfsPlatformValidateOpen(HgfsFileOpenInfo *openInfo, // IN: Open info struct
* Try to open the file with the requested mode, flags and permissions.
*/
fd = Posix_Open(openInfo->utf8Name,
- openMode | openFlags,
- openPerms);
+ openMode | openFlags,
+ openPerms);
if (fd < 0) {
- error = errno;
- LOG(4, ("%s: couldn't open file \"%s\": %s\n", __FUNCTION__,
- openInfo->utf8Name, strerror(error)));
- status = error;
+ status = errno;
+ if (status == EAGAIN) {
+ /*
+ * We have tried opening with O_NONBLOCK but looks like an incompatible
+ * lease may be held on the file. Tell the client that this access mode
+ * is not allowed currently.
+ */
+ status = EACCES;
+ }
+ LOG(4, ("%s: Error: open file \"%s\": %d %s\n", __FUNCTION__,
+ openInfo->utf8Name, status, strerror(status)));
goto exit;
}
/* Stat file to get its volume and file info */
if (fstat(fd, &fileStat) < 0) {
- error = errno;
- LOG(4, ("%s: couldn't stat local file \"%s\": %s\n", __FUNCTION__,
- openInfo->utf8Name, strerror(error)));
+ status = errno;
+ LOG(4, ("%s: Error: stat file\"%s\": %d %s\n", __FUNCTION__,
+ openInfo->utf8Name, status, strerror(status)));
close(fd);
- status = error;
goto exit;
}
@@ -1087,8 +1101,7 @@ HgfsPlatformValidateOpen(HgfsFileOpenInfo *openInfo, // IN: Open info struct
*
* Mac OS defines a special file type known as an alias which behaves like a
* symlink when viewed through the Finder, but is actually a regular file
- * otherwise. Unlike symlinks, aliases cannot be broken; if the target file
- * is deleted, so is the alias.
+ * otherwise.
*
* If the given filename is (or contains) an alias, this function will
* resolve it completely and set targetName to something non-NULL.
@@ -1111,109 +1124,214 @@ HgfsGetattrResolveAlias(char const *fileName, // IN: Input filename
#ifndef __APPLE__
*targetName = NULL;
return 0;
-#else
- char *myTargetName = NULL;
+#else // __APPLE__
HgfsInternalStatus status = HGFS_INTERNAL_STATUS_ERROR;
- CFURLRef resolvedRef = NULL;
- CFStringRef resolvedString;
- FSRef fileRef;
- Boolean targetIsFolder;
- Boolean wasAliased;
- OSStatus osStatus;
+ Boolean success;
+ CFURLRef resolvedURL = NULL;
+ CFStringRef resolvedString = NULL;
+ CFIndex maxPath;
- ASSERT_ON_COMPILE(sizeof osStatus == sizeof (int32));
+ *targetName = NULL;
- /*
- * Create and resolve an FSRef of the desired path. We pass FALSE to
- * resolveAliasChains because aliases to aliases should behave as
- * symlinks to symlinks. If the file is an alias, wasAliased will be set to
- * TRUE and fileRef will reference the target file.
- */
- osStatus = FSPathMakeRef(fileName, &fileRef, NULL);
- if (osStatus != noErr) {
- LOG(4, ("%s: could not create file reference: error %d\n",
- __FUNCTION__, (int32)osStatus));
- goto exit;
- }
- /*
- * If alias points to an unmounted volume, the volume needs to be explicitly
- * mounted on the host. Mount flag kResolveAliasFileNoUI serves the purpose.
- *
- * XXX: This function returns fnfErr (file not found) if it encounters a
- * broken alias. Perhaps we should make that look like a dangling symlink
- * instead of returning an error?
- *
- * XXX: It also returns errors if it encounters a file with a .alias suffix
- * that isn't a real alias. That's OK for now because our caller
- * (HgfsGetattrFromName) will assume that an error means the file is a
- * regular file.
- */
- osStatus = FSResolveAliasFileWithMountFlags(&fileRef, FALSE, &targetIsFolder,
- &wasAliased,
- kResolveAliasFileNoUI);
- if (osStatus != noErr) {
- LOG(4, ("%s: could not resolve reference: error %d\n",
- __FUNCTION__, (int32)osStatus));
- goto exit;
- }
+ if (CFURLCreateBookmarkDataFromFile != NULL) {
+ /* We are running on Mac OS 10.6 or later. */
+
+ CFURLRef fileURL;
+ CFBooleanRef isAlias = NULL;
+ CFDataRef bookmarkData = NULL;
+ CFURLBookmarkResolutionOptions resolutionOptions;
+ Boolean isStale;
+
+ fileURL = CFURLCreateFromFileSystemRepresentation(NULL, fileName,
+ strlen(fileName),
+ FALSE);
+ if (!fileURL) {
+ Log("%s: could not create CFURL for file.\n",
+ __FUNCTION__);
+ goto newExit;
+ }
- if (wasAliased) {
- CFIndex maxPath;
+ success = CFURLCopyResourcePropertyForKey(fileURL, kCFURLIsAliasFileKey,
+ &isAlias, NULL);
+ if (!success) {
+ Log("%s: could not copy IsAlias property key for file.\n",
+ __FUNCTION__);
+ goto newExit;
+ }
+ if (!CFBooleanGetValue(isAlias)) {
+ status = 0;
+ LOG(4, ("%s: file was not an alias\n", __FUNCTION__));
+ goto newExit;
+ }
+
+ LOG(4, ("%s: file was an alias\n", __FUNCTION__));
+
+ bookmarkData = CFURLCreateBookmarkDataFromFile(NULL, fileURL, NULL);
+ if (!bookmarkData) {
+ Log("%s: could not retrieve bookmark data for file.\n",
+ __FUNCTION__);
+ goto newExit;
+ }
/*
- * This is somewhat convoluted. We create a CFURL from the FSRef because
- * we want to call CFURLGetFileSystemRepresentation() to get a UTF-8
- * string representing the target of the alias. But to call
- * CFStringGetMaximumSizeOfFileSystemRepresentation(), we need a
- * CFString, so we make one from the CFURL. Once we've got the max number
- * of bytes for a filename on the filesystem, we allocate some memory
- * and convert the CFURL to a basic UTF-8 string using a call to
- * CFURLGetFileSystemRepresentation().
+ * Don't show any UI during alias resolution and don't mount volumes
+ * containing the alias target. This avoids blocking the current process
+ * and/or Finder while trying to mount unreachable hosts (bug 1396411).
*/
- resolvedRef = CFURLCreateFromFSRef(NULL, &fileRef);
- if (resolvedRef == NULL) {
- LOG(4, ("%s: could not create resolved URL reference from "
- "resolved filesystem reference\n", __FUNCTION__));
- goto exit;
+ resolutionOptions = kCFBookmarkResolutionWithoutUIMask |
+ kCFBookmarkResolutionWithoutMountingMask;
+
+ resolvedURL = CFURLCreateByResolvingBookmarkData(NULL, bookmarkData,
+ resolutionOptions,
+ NULL, NULL, &isStale,
+ NULL);
+ if (!resolvedURL) {
+ Log("%s: could not resolve bookmark data for file.\n",
+ __FUNCTION__);
+ goto newExit;
}
- resolvedString = CFURLGetString(resolvedRef);
- if (resolvedString == NULL) {
- LOG(4, ("%s: could not create resolved string reference from "
- "resolved URL reference\n", __FUNCTION__));
+
+newExit:
+ if (fileURL) {
+ CFRelease(fileURL);
+ }
+ if (isAlias) {
+ CFRelease(isAlias);
+ }
+ if (bookmarkData) {
+ CFRelease(bookmarkData);
+ }
+
+ } else {
+ /* We are running on Mac OS 10.5 or earlier. */
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ /*
+ * Mac OS 10.5 used a type of alias which appears on disk as a 0-byte
+ * file but stores its linking data in a resource fork. The APIs for
+ * interacting with this type of alias are deprecated when targetting
+ * 10.8+.
+ */
+ FSRef fileRef;
+ Boolean isAlias;
+ Boolean targetIsFolder;
+ OSStatus osStatus;
+
+ ASSERT_ON_COMPILE(sizeof osStatus == sizeof (int32));
+
+ osStatus = FSPathMakeRef(fileName, &fileRef, NULL);
+ if (osStatus != noErr) {
+ Log("%s: could not create file reference: error %d\n",
+ __FUNCTION__, (int32)osStatus);
+ goto oldExit;
+ }
+
+ osStatus = FSIsAliasFile(&fileRef, &isAlias, &targetIsFolder);
+ if (osStatus != noErr) {
+ Log("%s: could not detect if file is an old style alias: error %d\n",
+ __FUNCTION__, (int32)osStatus);
+ goto oldExit;
+ }
+
+ if (!isAlias) {
+ status = 0;
+ LOG(4, ("%s: file was not an alias\n", __FUNCTION__));
+ goto oldExit;
+ }
+
+ LOG(4, ("%s: file was an alias\n", __FUNCTION__));
+
+ /*
+ * Create and resolve an FSRef of the desired path. We pass FALSE to
+ * resolveAliasChains because aliases to aliases should behave as
+ * symlinks to symlinks.
+ *
+ * If alias points to an unmounted volume, the volume needs to be
+ * explicitly mounted. Mount flag kResolveAliasFileNoUI prevents the user
+ * from being prompted about mounting.
+ *
+ * Caution: Mac OS 10.10.2 will attempt to mount volumes silently,
+ * unlike the earlier behavior of only resolving within existing mounts.
+ * The new CFURLCreateByResolvingBookmarkData API must be used to avoid
+ * mounting the alias target.
+ *
+ * XXX: This function returns fnfErr (file not found) if it encounters a
+ * broken alias. Perhaps we should make that look like a dangling symlink
+ * instead of returning an error?
+ */
+ osStatus = FSResolveAliasFileWithMountFlags(&fileRef, FALSE,
+ &targetIsFolder, &isAlias,
+ kResolveAliasFileNoUI);
+ if (osStatus != noErr) {
+ Log("%s: could not resolve reference: error %d\n",
+ __FUNCTION__, (int32)osStatus);
+ goto oldExit;
+ }
+
+ resolvedURL = CFURLCreateFromFSRef(NULL, &fileRef);
+ if (!resolvedURL) {
+ Log("%s: could not create resolved URL reference from "
+ "resolved filesystem reference\n", __FUNCTION__);
+ goto oldExit;
+ }
+
+oldExit:
+ (void)0; // Need a statement for the label.
+#else // __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
+ // We are running on 10.5 but the build was targetting 10.6+. Eject!
+ NOT_IMPLEMENTED();
+#endif // __MAC_OS_X_VERSION_MIN_REQUIRED
+ }
+
+ if (resolvedURL) {
+ /*
+ * This is somewhat convoluted. We want to call
+ * CFURLGetFileSystemRepresentation() to get a UTF-8 string representing
+ * the target of the alias. But to call
+ * CFStringGetMaximumSizeOfFileSystemRepresentation(), we need a CFString,
+ * so we make one from the CFURL. Once we've got the max number of bytes
+ * for a filename on the filesystem, we allocate some memory and convert
+ * the CFURL to a basic UTF-8 string using a call to
+ * CFURLGetFileSystemRepresentation().
+ */
+ resolvedString = CFURLGetString(resolvedURL);
+ if (!resolvedString) {
+ Log("%s: could not create resolved string reference from "
+ "resolved URL reference\n", __FUNCTION__);
goto exit;
}
+
maxPath = CFStringGetMaximumSizeOfFileSystemRepresentation(resolvedString);
- myTargetName = malloc(maxPath);
- if (myTargetName == NULL) {
- LOG(4, ("%s: could not allocate %"FMTSZ"d bytes of memory for "
- "target name storage\n", __FUNCTION__, maxPath));
+ *targetName = malloc(maxPath);
+ if (*targetName == NULL) {
+ Log("%s: could not allocate %"FMTSZ"d bytes of memory for "
+ "target name storage\n", __FUNCTION__, maxPath);
goto exit;
}
- if (!CFURLGetFileSystemRepresentation(resolvedRef, FALSE, myTargetName,
- maxPath)) {
- LOG(4, ("%s: could not convert and copy resolved URL reference "
- "into allocated buffer\n", __FUNCTION__));
+
+ success = CFURLGetFileSystemRepresentation(resolvedURL, FALSE,
+ *targetName, maxPath);
+ if (!success) {
+ Log("%s: could not convert and copy resolved URL reference "
+ "into allocated buffer\n", __FUNCTION__);
goto exit;
}
- *targetName = myTargetName;
- LOG(4, ("%s: file was an alias\n", __FUNCTION__));
- } else {
- *targetName = NULL;
- LOG(4, ("%s: file was not an alias\n", __FUNCTION__));
+ status = 0;
}
- status = 0;
- exit:
+exit:
+ if (resolvedURL) {
+ CFRelease(resolvedURL);
+ }
if (status != 0) {
- free(myTargetName);
+ free(*targetName);
+ *targetName = NULL;
}
- if (resolvedRef != NULL) {
- CFRelease(resolvedRef);
- }
return status;
-#endif
+
+#endif // __APPLE__
}
@@ -1343,7 +1461,7 @@ HgfsConvertComponentCase(char *currentComponent, // IN
* to lower case and then compare it to the lower case component.
*/
while ((dirent = readdir(dir))) {
- Unicode dentryNameU;
+ char *dentryNameU;
int cmpResult;
dentryName = dirent->d_name;
@@ -1364,7 +1482,7 @@ HgfsConvertComponentCase(char *currentComponent, // IN
dentryNameU = Unicode_Alloc(dentryName, STRING_ENCODING_DEFAULT);
cmpResult = Unicode_CompareIgnoreCase(currentComponent, dentryNameU);
- Unicode_Free(dentryNameU);
+ free(dentryNameU);
if (cmpResult == 0) {
/*
@@ -1465,7 +1583,7 @@ HgfsConstructConvertedPath(char **path, // IN/OUT
*
* Results:
* Returns 0 if successful and resolved path for fileName is returned in
- * convertedFileName with its length in convertedFileNameLength.
+ * convertedFileName and its length (without nul) in convertedFileNameLength.
* Otherwise returns non-zero errno with convertedFileName and
* convertedFileNameLength set to NULL and 0 respectively.
*
@@ -1485,35 +1603,35 @@ HgfsCaseInsensitiveLookup(const char *sharePath, // IN
size_t *convertedFileNameLength) // OUT
{
char *currentComponent;
- char *curDir;
char *nextComponent;
- int error = ENOENT;
+ char *curDir;
size_t curDirSize;
char *convertedComponent = NULL;
size_t convertedComponentSize = 0;
+ int error = 0;
ASSERT(sharePath);
ASSERT(fileName);
ASSERT(convertedFileName);
ASSERT(fileNameLength >= sharePathLength);
+ curDirSize = sharePathLength + 1;
+ curDir = malloc(curDirSize);
+ if (!curDir) {
+ error = errno;
+ LOG(4, ("%s: failed to allocate for curDir\n", __FUNCTION__));
+ goto exit;
+ }
+ Str_Strcpy(curDir, sharePath, curDirSize);
+
currentComponent = fileName + sharePathLength;
/* Check there is something beyond the share name. */
if (*currentComponent == '\0') {
/*
* The fileName is the same as sharePath. Nothing else to do.
- * Dup the string and return.
+ * Return the duplicated sharePath string and return.
*/
- *convertedFileName = strdup(fileName);
- if (!*convertedFileName) {
- error = errno;
- *convertedFileName = NULL;
- *convertedFileNameLength = 0;
- LOG(4, ("%s: strdup on fileName failed.\n", __FUNCTION__));
- } else {
- *convertedFileNameLength = strlen(fileName);
- }
- return 0;
+ goto exit;
}
/* Skip a component separator if not in the share path. */
@@ -1521,15 +1639,6 @@ HgfsCaseInsensitiveLookup(const char *sharePath, // IN
currentComponent += 1;
}
- curDirSize = sharePathLength + 1;
- curDir = malloc(curDirSize);
- if (!curDir) {
- error = errno;
- LOG(4, ("%s: failed to allocate for curDir\n", __FUNCTION__));
- goto exit;
- }
- Str_Strcpy(curDir, sharePath, curDirSize);
-
while (TRUE) {
/* Get the next component. */
nextComponent = strchr(currentComponent, DIRSEPC);
@@ -1553,21 +1662,15 @@ HgfsCaseInsensitiveLookup(const char *sharePath, // IN
if (error) {
if (error == ENOENT) {
- int ret;
/*
+ * We could not find the current component so no need to convert it.
+ * So it most likely a new path is to be created or an ENOENT genuine error.
* Copy out the components starting from currentComponent. We do this
* after replacing DIRSEPC, so all the components following
* currentComponent gets copied.
*/
- ret = HgfsConstructConvertedPath(&curDir, &curDirSize, currentComponent,
- strlen(currentComponent) + 1);
- if (ret) {
- error = ret;
- }
- }
-
- if (error != ENOENT) {
- free(curDir);
+ error = HgfsConstructConvertedPath(&curDir, &curDirSize, currentComponent,
+ strlen(currentComponent) + 1);
}
break;
}
@@ -1576,13 +1679,12 @@ HgfsCaseInsensitiveLookup(const char *sharePath, // IN
error = HgfsConstructConvertedPath(&curDir, &curDirSize, convertedComponent,
convertedComponentSize);
if (error) {
- free(curDir);
- free(convertedComponent);
break;
}
/* Free the converted component. */
free(convertedComponent);
+ convertedComponent = NULL;
/* If there is no component after the current one then we are done. */
if (nextComponent == NULL) {
@@ -1598,17 +1700,20 @@ HgfsCaseInsensitiveLookup(const char *sharePath, // IN
currentComponent = nextComponent + 1;
}
- /* If the conversion was successful, return the result. */
- if (error == 0 || error == ENOENT) {
- *convertedFileName = curDir;
- *convertedFileNameLength = curDirSize;
- }
-
exit:
- if (error && error != ENOENT) {
+ /*
+ * If the conversion was successful, return the result.
+ * The length does NOT include the nul terminator.
+ */
+ if (error == 0) {
+ *convertedFileName = curDir;
+ *convertedFileNameLength = curDirSize - 1;
+ } else {
*convertedFileName = NULL;
*convertedFileNameLength = 0;
+ free(curDir);
}
+ free(convertedComponent);
return error;
}
@@ -1677,17 +1782,15 @@ HgfsPlatformFilenameLookup(const char *sharePath, // IN
convertedFileNameLength);
/*
- * Success or non-ENOENT error code. HgfsCaseInsensitiveLookup can
- * return ENOENT, and its ok to continue if it is ENOENT.
+ * Map the success or an error code.
*/
switch (error) {
/*
- * Both ENOENT and 0 mean that HgfsCaseInsensitiveLookup
+ * 0 means that HgfsCaseInsensitiveLookup completed
* successfully built the converted name thus we return
- * HGFS_NAME_STATUS_COMPLETE in these two cases.
+ * HGFS_NAME_STATUS_COMPLETE in this case.
*/
case 0:
- case ENOENT:
nameStatus = HGFS_NAME_STATUS_COMPLETE;
break;
case ENOTDIR:
@@ -2221,6 +2324,7 @@ HgfsPlatformGetattrFromName(char *fileName, // IN/OUT: Input fi
*targetName = myTargetName;
myTargetName = NULL;
#endif
+ LOG(4, ("%s: symlink target \"%s\"\n", __FUNCTION__, *targetName));
}
HgfsStatToFileAttr(&stats, &creationTime, attr);
@@ -2401,6 +2505,7 @@ HgfsStatToFileAttr(struct stat *stats, // IN: stat information
HgfsFileAttrInfo *attr) // OUT: FileAttrInfo to copy into
{
attr->size = stats->st_size;
+ attr->allocationSize = stats->st_blocks * 512;
attr->creationTime = *creationTime;
#ifdef __FreeBSD__
@@ -2468,6 +2573,7 @@ HgfsStatToFileAttr(struct stat *stats, // IN: stat information
attr->volumeId = stats->st_dev;
attr->mask = HGFS_ATTR_VALID_TYPE |
HGFS_ATTR_VALID_SIZE |
+ HGFS_ATTR_VALID_ALLOCATION_SIZE |
HGFS_ATTR_VALID_CREATE_TIME |
HGFS_ATTR_VALID_ACCESS_TIME |
HGFS_ATTR_VALID_WRITE_TIME |
@@ -2513,7 +2619,7 @@ HgfsSetattrMode(struct stat *statBuf, // IN: stat info
ASSERT(attr);
ASSERT(newPermissions);
- *newPermissions = ~ALLPERMS;
+ *newPermissions = 0;
if (attr->mask & HGFS_ATTR_VALID_SPECIAL_PERMS) {
*newPermissions |= attr->specialPerms << 9;
permsChanged = TRUE;
@@ -2776,11 +2882,26 @@ HgfsPlatformSetattrFromFd(HgfsHandle file, // IN: file descriptor
* if all operations succeeded.
*/
+ idChanged = HgfsSetattrOwnership(attr, &newUid, &newGid);
+ if (idChanged) {
+ LOG(4, ("%s: set uid %"FMTUID" and gid %"FMTUID"\n", __FUNCTION__,
+ newUid, newGid));
+ if (fchown(fd, newUid, newGid) < 0) {
+ error = errno;
+ LOG(4, ("%s: error chowning file %u: %s\n", __FUNCTION__,
+ fd, strerror(error)));
+ status = error;
+ }
+ }
+
/*
* Set permissions based on what we got in the packet. If we didn't get
* a particular bit, use the existing permissions. In that case we don't
* toggle permsChanged since it should not influence our decision of
* whether to actually call chmod or not.
+ *
+ * NOTE: Setting ownership clears SUID and SGID bits, therefore set the
+ * file permissions after setting ownership.
*/
permsChanged = HgfsSetattrMode(&statBuf, attr, &newPermissions);
if (permsChanged) {
@@ -2794,18 +2915,6 @@ HgfsPlatformSetattrFromFd(HgfsHandle file, // IN: file descriptor
}
}
- idChanged = HgfsSetattrOwnership(attr, &newUid, &newGid);
- if (idChanged) {
- LOG(4, ("%s: set uid %"FMTUID" and gid %"FMTUID"\n", __FUNCTION__,
- newUid, newGid));
- if (fchown(fd, newUid, newGid) < 0) {
- error = errno;
- LOG(4, ("%s: error chowning file %u: %s\n", __FUNCTION__,
- fd, strerror(error)));
- status = error;
- }
- }
-
if (attr->mask & HGFS_ATTR_VALID_SIZE) {
/*
* XXX: Truncating the file will trigger an oplock break. The client
@@ -2981,11 +3090,28 @@ HgfsPlatformSetattrFromName(char *localName, // IN: Name
* if all operations succeeded.
*/
+ idChanged = HgfsSetattrOwnership(attr, &newUid, &newGid);
+ /*
+ * Chown changes the uid and gid together. If one of them should
+ * not be changed, we pass in -1.
+ */
+ if (idChanged) {
+ if (Posix_Lchown(localName, newUid, newGid) < 0) {
+ error = errno;
+ LOG(4, ("%s: error chowning file \"%s\": %s\n", __FUNCTION__,
+ localName, strerror(error)));
+ status = error;
+ }
+ }
+
/*
* Set permissions based on what we got in the packet. If we didn't get
* a particular bit, use the existing permissions. In that case we don't
* toggle permsChanged since it should not influence our decision of
* whether to actually call chmod or not.
+ *
+ * NOTE: Setting ownership clears SUID and SGID bits, therefore set the
+ * file permissions after setting ownership.
*/
permsChanged = HgfsSetattrMode(&statBuf, attr, &newPermissions);
if (permsChanged) {
@@ -2999,20 +3125,6 @@ HgfsPlatformSetattrFromName(char *localName, // IN: Name
}
}
- idChanged = HgfsSetattrOwnership(attr, &newUid, &newGid);
- /*
- * Chown changes the uid and gid together. If one of them should
- * not be changed, we pass in -1.
- */
- if (idChanged) {
- if (Posix_Lchown(localName, newUid, newGid) < 0) {
- error = errno;
- LOG(4, ("%s: error chowning file \"%s\": %s\n", __FUNCTION__,
- localName, strerror(error)));
- status = error;
- }
- }
-
if (attr->mask & HGFS_ATTR_VALID_SIZE) {
if (Posix_Truncate(localName, attr->size) < 0) {
error = errno;
@@ -3107,9 +3219,9 @@ HgfsPlatformVDirStatsFs(HgfsSessionInfo *session, // IN: session info
*/
LOG(4,("%s: opened search on base\n", __FUNCTION__));
- status = HgfsServerSearchVirtualDir(HgfsServerPolicy_GetShares,
- HgfsServerPolicy_GetSharesInit,
- HgfsServerPolicy_GetSharesCleanup,
+ status = HgfsServerSearchVirtualDir(HgfsServerResEnumGet,
+ HgfsServerResEnumInit,
+ HgfsServerResEnumExit,
DIRECTORY_SEARCH_TYPE_BASE,
session,
&handle);
@@ -3820,12 +3932,12 @@ HgfsPlatformScandir(char const *baseDir, // IN: Directory to search i
*/
HgfsInternalStatus
-HgfsPlatformScanvdir(HgfsGetNameFunc enumNamesGet, // IN: Function to get name
- HgfsInitFunc enumNamesInit, // IN: Setup function
- HgfsCleanupFunc enumNamesExit, // IN: Cleanup function
- DirectorySearchType type, // IN: Kind of search - unused
- struct DirectoryEntry ***dents, // OUT: Array of DirectoryEntrys
- uint32 *numDents) // OUT: total number of directory entrys
+HgfsPlatformScanvdir(HgfsServerResEnumGetFunc enumNamesGet, // IN: Function to get name
+ HgfsServerResEnumInitFunc enumNamesInit, // IN: Setup function
+ HgfsServerResEnumExitFunc enumNamesExit, // IN: Cleanup function
+ DirectorySearchType type, // IN: Kind of search - unused
+ struct DirectoryEntry ***dents, // OUT: Array of DirectoryEntrys
+ uint32 *numDents) // OUT: total number of directory entrys
{
HgfsInternalStatus status = HGFS_ERROR_SUCCESS;
uint32 totalDents = 0; // Number of allocated dents
@@ -4028,16 +4140,16 @@ exit:
*/
HgfsInternalStatus
-HgfsPlatformReadFile(HgfsHandle file, // IN: Hgfs file handle
+HgfsPlatformReadFile(fileDesc file, // IN: file descriptor
HgfsSessionInfo *session, // IN: session info
uint64 offset, // IN: file offset to read from
uint32 requiredSize, // IN: length of data to read
void* payload, // OUT: buffer for the read data
uint32 *actualSize) // OUT: actual length read
{
- int fd;
int error;
- HgfsInternalStatus status;
+ HgfsInternalStatus status = 0;
+ HgfsHandle handle;
Bool sequentialOpen;
ASSERT(session);
@@ -4046,15 +4158,12 @@ HgfsPlatformReadFile(HgfsHandle file, // IN: Hgfs file handle
LOG(4, ("%s: read fh %u, offset %"FMT64"u, count %u\n", __FUNCTION__,
file, offset, requiredSize));
- /* Get the file descriptor from the cache */
- status = HgfsPlatformGetFd(file, session, FALSE, &fd);
-
- if (status != 0) {
- LOG(4, ("%s: Could not get file descriptor\n", __FUNCTION__));
- return status;
+ if (!HgfsFileDesc2Handle(file, session, &handle)) {
+ LOG(4, ("%s: Could not get file handle\n", __FUNCTION__));
+ return EBADF;
}
- if (!HgfsHandleIsSequentialOpen(file, session, &sequentialOpen)) {
+ if (!HgfsHandleIsSequentialOpen(handle, session, &sequentialOpen)) {
LOG(4, ("%s: Could not get sequenial open status\n", __FUNCTION__));
return EBADF;
}
@@ -4062,9 +4171,9 @@ HgfsPlatformReadFile(HgfsHandle file, // IN: Hgfs file handle
#if defined(__linux__) || defined(__APPLE__)
/* Read from the file. */
if (sequentialOpen) {
- error = read(fd, payload, requiredSize);
+ error = read(file, payload, requiredSize);
} else {
- error = pread(fd, payload, requiredSize, offset);
+ error = pread(file, payload, requiredSize, offset);
}
#else
/*
@@ -4081,18 +4190,18 @@ HgfsPlatformReadFile(HgfsHandle file, // IN: Hgfs file handle
{
uint64 res;
# if !defined(VM_X86_64)
- error = _llseek(fd, offset >> 32, offset & 0xFFFFFFFF, &res, 0);
+ error = _llseek(file, offset >> 32, offset & 0xFFFFFFFF, &res, 0);
# else
- error = llseek(fd, offset >> 32, offset & 0xFFFFFFFF, &res, 0);
+ error = llseek(file, offset >> 32, offset & 0xFFFFFFFF, &res, 0);
# endif
}
# else
- error = lseek(fd, offset, 0);
+ error = lseek(file, offset, 0);
# endif
}
if (error >= 0) {
- error = read(fd, payload, requiredSize);
+ error = read(file, payload, requiredSize);
} else {
LOG(4, ("%s: could not seek to %"FMT64"u: %s\n", __FUNCTION__,
offset, strerror(status)));
@@ -4162,6 +4271,15 @@ HgfsPlatformWriteFile(HgfsHandle file, // IN: Hgfs file handle
return EBADF;
}
+#if !defined(sun)
+ if (!sequentialOpen) {
+ status = HgfsWriteCheckIORange(offset, requiredSize);
+ if (status != 0) {
+ return status;
+ }
+ }
+#endif
+
#if defined(__linux__)
/* Write to the file. */
if (sequentialOpen) {
@@ -4253,7 +4371,7 @@ HgfsPlatformWriteFile(HgfsHandle file, // IN: Hgfs file handle
HgfsInternalStatus
HgfsPlatformSearchDir(HgfsNameStatus nameStatus, // IN: name status
const char *dirName, // IN: relative directory name
- uint32 dirNameLength, // IN: length of dirName
+ size_t dirNameLength, // IN: length of dirName
uint32 caseFlags, // IN: case flags
HgfsShareInfo *shareInfo, // IN: sharfed folder information
char *baseDir, // IN: name of the shared directory
@@ -4321,9 +4439,9 @@ HgfsPlatformSearchDir(HgfsNameStatus nameStatus, // IN: name status
*/
LOG(4, ("%s: opened search on base\n", __FUNCTION__));
- status = HgfsServerSearchVirtualDir(HgfsServerPolicy_GetShares,
- HgfsServerPolicy_GetSharesInit,
- HgfsServerPolicy_GetSharesCleanup,
+ status = HgfsServerSearchVirtualDir(HgfsServerResEnumGet,
+ HgfsServerResEnumInit,
+ HgfsServerResEnumExit,
DIRECTORY_SEARCH_TYPE_BASE,
session,
handle);
@@ -4371,9 +4489,9 @@ HgfsPlatformRestartSearchDir(HgfsHandle handle, // IN: search hand
switch (searchType) {
case DIRECTORY_SEARCH_TYPE_BASE:
/* Entries are shares */
- status = HgfsServerRestartSearchVirtualDir(HgfsServerPolicy_GetShares,
- HgfsServerPolicy_GetSharesInit,
- HgfsServerPolicy_GetSharesCleanup,
+ status = HgfsServerRestartSearchVirtualDir(HgfsServerResEnumGet,
+ HgfsServerResEnumInit,
+ HgfsServerResEnumExit,
session,
handle);
break;
@@ -4690,7 +4808,7 @@ HgfsPlatformCreateDir(HgfsCreateDirInfo *info, // IN: direcotry properties
* a directory requires a valid mode, it's highly unlikely that we'll ever
* be creating a directory without owner permissions.
*/
- permissions = ~ALLPERMS;
+ permissions = 0;
permissions |= info->mask & HGFS_CREATE_DIR_VALID_SPECIAL_PERMS ?
info->specialPerms << 9 : 0;
permissions |= info->mask & HGFS_CREATE_DIR_VALID_OWNER_PERMS ?
@@ -4745,6 +4863,8 @@ HgfsPlatformSymlinkCreate(char *localSymlinkName, // IN: symbolic link file na
HgfsInternalStatus status = 0;
int error;
+ LOG(4, ("%s: %s -> %s\n", __FUNCTION__, localSymlinkName, localTargetName));
+
/* XXX: Should make use of targetNameP->flags? */
error = Posix_Symlink(localTargetName, localSymlinkName);
if (error) {
@@ -5155,3 +5275,64 @@ HgfsSetHiddenXAttr(char const *fileName, // IN: File name
return 0;
}
#endif // __APPLE__
+
+
+#if !defined(sun)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsWriteCheckIORange --
+ *
+ * Verifies that the write arguments do not exceed the maxiuum file size.
+ *
+ * Results:
+ * 0 on success, otherwise an appropriate error.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static HgfsInternalStatus
+HgfsWriteCheckIORange(off_t offset, // IN:
+ uint32 bytesToWrite) // IN:
+{
+ HgfsInternalStatus status = 0;
+ struct rlimit fileSize;
+
+ if (getrlimit(RLIMIT_FSIZE, &fileSize) < 0) {
+ status = errno;
+ LOG(4, ("%s: Could not get file size limit\n", __FUNCTION__));
+ goto exit;
+ }
+
+ LOG(6, ("%s: File Size limits: 0x%"FMT64"x 0x%"FMT64"x\n",
+ __FUNCTION__, fileSize.rlim_cur, fileSize.rlim_max));
+
+ /*
+ * Check the offset is within the file size range.
+ */
+ if (fileSize.rlim_cur < offset) {
+ status = EFBIG;
+ LOG(4, ("%s: Write offset exceeds max file size limit - 0x%"FMT64"x\n",
+ __FUNCTION__, offset));
+ goto exit;
+ }
+
+ /*
+ * Check the data to write does not exceed the max file size.
+ */
+ if (fileSize.rlim_cur - offset < bytesToWrite) {
+ status = EFBIG;
+ LOG(4, ("%s: Write data 0x%x bytes @ 0x%"FMT64"x size exceeds max file size\n",
+ __FUNCTION__, bytesToWrite, offset));
+ goto exit;
+ }
+
+exit:
+ LOG(6, ("%s: Write data 0x%x bytes @ 0x%"FMT64"x returns %d\n",
+ __FUNCTION__, bytesToWrite, offset, status));
+ return status;
+}
+#endif
diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c b/open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c
index 45b72b74..2294382e 100644
--- a/open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c
+++ b/open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c
@@ -38,6 +38,7 @@ static void *HSPUGetBuf(HgfsServerChannelCallbacks *chanCb,
HgfsVmxIov *iov,
uint32 iovCount,
uint32 startIndex,
+ size_t dataSize,
size_t bufSize,
void **buf,
Bool *isAllocated,
@@ -74,6 +75,65 @@ static void HSPUUnmapBuf(HgfsChannelUnmapVirtAddrFunc unmapVa,
uint32 *mappedCount);
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HSPU_ValidateReplyPacketSize --
+ *
+ * Validate a reply buffer size in an hgfs packet with the reply data
+ * size for the request.
+ *
+ * Results:
+ * TRUE if the reply buffer size is large enough for the request reply
+ * results. FALSE if not.
+ *
+ * Side effects:
+ * None.
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+HSPU_ValidateReplyPacketSize(HgfsPacket *packet, // IN: Hgfs Packet
+ size_t replyHeaderSize, // IN: reply header size
+ size_t replyResultSize, // IN: reply result size
+ size_t replyResultDataSize, // IN: reply result data size
+ Bool useMappedMetaPacket) // IN: using meta buffer
+{
+ size_t bytesRemaining;
+ Bool replySizeIsOkay = FALSE;
+
+ if (packet->replyPacket != NULL) {
+ /* Pre-allocated reply buffer (as used by the backdoor). */
+ bytesRemaining = packet->replyPacketSize;
+ } else if (useMappedMetaPacket) {
+ /* No reply buffer (as used by the VMCI) reuse the metapacket buffer. */
+ bytesRemaining = packet->metaPacketSize;
+ } else {
+ /* No reply buffer but we will allocate the size required. */
+ replySizeIsOkay = TRUE;
+ goto exit;
+ }
+
+ if (bytesRemaining >= replyHeaderSize) {
+ bytesRemaining -= replyHeaderSize;
+ } else {
+ goto exit;
+ }
+ if (bytesRemaining >= replyResultSize) {
+ bytesRemaining -= replyResultSize;
+ } else {
+ goto exit;
+ }
+ if (bytesRemaining >= replyResultDataSize) {
+ replySizeIsOkay = TRUE;
+ }
+
+exit:
+ return replySizeIsOkay;
+}
+
+
/*
*-----------------------------------------------------------------------------
*
@@ -117,7 +177,6 @@ HSPU_GetReplyPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
* is always mapped and copied no matter how much data it really contains.
*/
LOG(10, ("%s Using meta packet for reply packet\n", __FUNCTION__));
- ASSERT(replyDataSize <= packet->metaPacketDataSize);
ASSERT(BUF_READWRITEABLE == packet->metaMappingType);
ASSERT(replyDataSize <= packet->metaPacketSize);
@@ -222,6 +281,7 @@ HSPU_GetMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
packet->iovCount,
0,
packet->metaPacketDataSize,
+ packet->metaPacketSize,
&packet->metaPacket,
&packet->metaPacketIsAllocated,
&packet->metaPacketMappedIov);
@@ -231,6 +291,31 @@ HSPU_GetMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
/*
*-----------------------------------------------------------------------------
*
+ * HSPU_ValidateDataPacketSize --
+ *
+ * Validate a data packet buffer size in an hgfs packet with the required data
+ * size for the request.
+ *
+ * Results:
+ * TRUE if the data buffer size is valid for the request.
+ * FALSE if not.
+ *
+ * Side effects:
+ * None.
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+HSPU_ValidateDataPacketSize(HgfsPacket *packet, // IN: Hgfs Packet
+ size_t dataSize) // IN: data size
+{
+ return (dataSize <= packet->dataPacketSize);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* HSPU_GetDataPacketBuf --
*
* Get a data packet given an hgfs packet.
@@ -263,6 +348,7 @@ HSPU_GetDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Pack
packet->iov,
packet->iovCount,
packet->dataPacketIovIndex,
+ packet->dataPacketDataSize,
packet->dataPacketSize,
&packet->dataPacket,
&packet->dataPacketIsAllocated,
@@ -292,6 +378,7 @@ HSPUGetBuf(HgfsServerChannelCallbacks *chanCb, // IN: Channel callbacks
HgfsVmxIov *iov, // IN: iov array
uint32 iovCount, // IN: iov array size
uint32 startIndex, // IN: Start index of iov
+ size_t dataSize, // IN: Size of data in tghe buffer
size_t bufSize, // IN: Size of buffer
void **buf, // OUT: Contigous buffer
Bool *isAllocated, // OUT: Buffer allocated
@@ -348,9 +435,9 @@ HSPUGetBuf(HgfsServerChannelCallbacks *chanCb, // IN: Channel callbacks
*buf = Util_SafeMalloc(bufSize);
*isAllocated = TRUE;
- if (mappingType == BUF_READABLE ||
- mappingType == BUF_READWRITEABLE) {
- HSPUCopyIovecToBuf(iov, iovMapped, startIndex, *buf, bufSize);
+ if ((mappingType == BUF_READABLE || mappingType == BUF_READWRITEABLE) &&
+ (0 != dataSize)) {
+ HSPUCopyIovecToBuf(iov, iovMapped, startIndex, *buf, dataSize);
}
releaseMappings = TRUE;
@@ -405,6 +492,31 @@ HSPU_PutMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
/*
*-----------------------------------------------------------------------------
*
+ * HSPU_SetDataPacketSize --
+ *
+ * Set the size of the valid data in the data packet buffer.
+ *
+ * Results:
+ * void.
+ *
+ * Side effects:
+ * None.
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HSPU_SetDataPacketSize(HgfsPacket *packet, // IN/OUT: Hgfs Packet
+ size_t dataSize) // IN: data size
+{
+ ASSERT(NULL != packet);
+ ASSERT(dataSize <= packet->dataPacketSize);
+ packet->dataPacketDataSize = dataSize;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* HSPU_PutDataPacketBuf --
*
* Free data packet buffer if allocated.
@@ -432,7 +544,7 @@ HSPU_PutDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Pack
packet->iov,
packet->iovCount,
packet->dataPacketIovIndex,
- packet->dataPacketSize,
+ packet->dataPacketDataSize,
&packet->dataPacket,
&packet->dataPacketIsAllocated,
&packet->dataPacketMappedIov);
diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerParameters.c b/open-vm-tools/lib/hgfsServer/hgfsServerParameters.c
index 5033cb1f..e17bb886 100644
--- a/open-vm-tools/lib/hgfsServer/hgfsServerParameters.c
+++ b/open-vm-tools/lib/hgfsServer/hgfsServerParameters.c
@@ -402,7 +402,7 @@ HgfsUnpackPacketParams(const void *packet, // IN: HGFS packet
ASSERT(NULL != packet);
request = packet;
- LOG(4, ("%s: Received a request with opcode %d.\n", __FUNCTION__, (int) request->op));
+ LOG(4, ("%s: Received a request with opcode %d.\n", __FUNCTION__, request->op));
/*
* Error out if less than HgfsRequest size.
@@ -466,6 +466,8 @@ HgfsUnpackPacketParams(const void *packet, // IN: HGFS packet
}
exit:
+ LOG(4, ("%s: unpacked request(op %d, id %u) -> %u.\n", __FUNCTION__,
+ request->op, *requestId, unpackStatus));
return unpackStatus;
}
@@ -893,6 +895,7 @@ HgfsPackOpenReplyV3(HgfsFileOpenInfo *openInfo, // IN: open info struct
{
reply->file = openInfo->file;
reply->reserved = 0;
+ reply->flags = 0;
if (openInfo->mask & HGFS_OPEN_VALID_SERVER_LOCK) {
reply->acquiredLock = openInfo->acquiredLock;
} else {
@@ -2477,7 +2480,7 @@ HgfsPackGetattrReplyPayloadV3(HgfsFileAttrInfo *attr, // IN: attr stucture
uint32 utf8TargetNameLen, // IN: file name length
HgfsReplyGetattrV3 *reply) // OUT: payload
{
- LOG(4, ("%s: attr type: %u\n", __FUNCTION__, reply->attr.type));
+ LOG(4, ("%s: attr type: %u\n", __FUNCTION__, attr->type));
HgfsPackAttrV2(attr, &reply->attr);
reply->reserved = 0;
@@ -4845,10 +4848,16 @@ HgfsUnpackSymlinkCreatePayloadV3(const HgfsRequestSymlinkCreateV3 *requestV3, //
srcNameLength,
srcFile,
srcCaseFlags)) {
- HgfsFileNameV3 *targetName = (HgfsFileNameV3 *)(*srcFileName + 1 +
- *srcNameLength);
+ const HgfsFileNameV3 *targetName;
+
+ if (*srcUseHandle) {
+ targetName = &requestV3->targetName;
+ } else {
+ targetName = (const HgfsFileNameV3 *)(*srcFileName + 1 +
+ *srcNameLength);
+ }
prefixSize = ((char *)targetName - (char *)requestV3) +
- offsetof(HgfsFileNameV3, name);
+ offsetof(HgfsFileNameV3, name);
return HgfsUnpackFileNameV3(targetName,
payloadSize - prefixSize,
@@ -5017,7 +5026,7 @@ static Bool
HgfsUnpackSearchOpenPayload(const HgfsRequestSearchOpen *request, // IN: payload
size_t payloadSize, // IN: payload size
const char **dirName, // OUT: directory name
- uint32 *dirNameLength) // OUT: name length
+ size_t *dirNameLength) // OUT: name length
{
LOG(4, ("%s: HGFS_OP_SEARCH_OPEN\n", __FUNCTION__));
if (payloadSize >= sizeof *request) {
@@ -5054,20 +5063,30 @@ static Bool
HgfsUnpackSearchOpenPayloadV3(const HgfsRequestSearchOpenV3 *requestV3, // IN: payload
size_t payloadSize, // IN: payload size
const char **dirName, // OUT: directory name
- uint32 *dirNameLength, // OUT: name length
+ size_t *dirNameLength, // OUT: name length
uint32 *caseFlags) // OUT: case flags
{
+ Bool result = FALSE;
LOG(4, ("%s: HGFS_OP_SEARCH_OPEN_V3\n", __FUNCTION__));
if (payloadSize >= sizeof *requestV3) {
- if (sizeof *requestV3 + requestV3->dirName.length - 1 <= payloadSize) {
- *dirName = requestV3->dirName.name;
- *dirNameLength = requestV3->dirName.length;
- *caseFlags = requestV3->dirName.flags;
- return TRUE;
+ uint32 prefixSize = offsetof(HgfsRequestSearchOpenV3, dirName.name);
+ Bool useDirHandle;
+ HgfsHandle dirHandle;
+
+ result = HgfsUnpackFileNameV3(&requestV3->dirName,
+ payloadSize - prefixSize,
+ &useDirHandle,
+ dirName,
+ dirNameLength,
+ &dirHandle,
+ caseFlags);
+ if (useDirHandle) {
+ LOG(4, ("%s: client is trying to a handle %u\n", __FUNCTION__, dirHandle));
+ result = FALSE;
}
}
- LOG(4, ("%s: HGFS packet too small\n", __FUNCTION__));
- return FALSE;
+ LOG(4, ("%s: returns %d\n", __FUNCTION__, result));
+ return result;
}
@@ -5093,7 +5112,7 @@ HgfsUnpackSearchOpenRequest(const void *packet, // IN: HGFS packet
size_t packetSize, // IN: request packet size
HgfsOp op, // IN: request type
const char **dirName, // OUT: directory name
- uint32 *dirNameLength, // OUT: name length
+ size_t *dirNameLength, // OUT: name length
uint32 *caseFlags) // OUT: case flags
{
ASSERT(packet);
@@ -5898,7 +5917,7 @@ HgfsUnpackOplockBreakAckReply(const void *packet, // IN: HGFS packet
}
if (!result) {
- LOG(4, ("%s: Error unpacking packet\n", __FUNCTION__));
+ LOG(4, ("%s: Error unpacking HGFS_OP_OPLOCK_BREAK_V4 packet\n", __FUNCTION__));
}
return result;
}
@@ -5921,7 +5940,7 @@ HgfsUnpackOplockBreakAckReply(const void *packet, // IN: HGFS packet
*-----------------------------------------------------------------------------
*/
-static size_t
+static int
HgfsBuildCPName(char const *shareName, // IN: utf8 share name
char *fileName, // IN: utf8 file path
char **cpName) // OUT: full name in cp format
@@ -5929,18 +5948,22 @@ HgfsBuildCPName(char const *shareName, // IN: utf8 share name
size_t shareNameLen = strlen(shareName) + 1;
size_t fileNameLen = strlen(fileName) + 1;
char *fullName = Util_SafeMalloc(shareNameLen + fileNameLen);
- size_t result;
+ int cpNameResult;
*cpName = Util_SafeMalloc(shareNameLen + fileNameLen);
Str_Strcpy(fullName, shareName, shareNameLen);
fullName[shareNameLen - 1] = DIRSEPC;
Str_Strcpy(fullName + shareNameLen, fileName, fileNameLen);
- result = CPName_ConvertTo(fullName, shareNameLen + fileNameLen, *cpName);
- ASSERT(result > 0); // Unescaped name can't be longer then escaped thus it must fit.
+ // Unescaped name can't be longer then escaped thus it must fit.
+ cpNameResult = CPName_ConvertTo(fullName, shareNameLen + fileNameLen, *cpName);
free(fullName);
+ if (cpNameResult < 0) {
+ free(*cpName);
+ *cpName = NULL;
+ }
- return result;
+ return cpNameResult;
}
@@ -6002,34 +6025,45 @@ HgfsPackChangeNotifyEventV4(uint32 mask, // IN: event mask
size_t bufferSize, // IN: available space
HgfsNotifyEventV4 *reply) // OUT: notificaiton buffer
{
- size_t totalLength;
+ size_t totalLength = 0;
if (sizeof *reply > bufferSize) {
- return 0;
+ /* Not enough space for the event, drop the event. */
+ goto exit;
}
reply->nextOffset = 0;
reply->mask = mask;
if (NULL != fileName) {
- char *fullPath;
+ char *cpFullName;
size_t remainingSize;
- size_t nameSize;
size_t hgfsNameSize;
+ int cpFullNameSize;
- nameSize = HgfsBuildCPName(shareName, fileName, &fullPath);
+ cpFullNameSize = HgfsBuildCPName(shareName, fileName, &cpFullName);
+ if (cpFullNameSize < 0) {
+ /* Could not build the crossplatform name, drop the event. */
+ goto exit;
+ }
remainingSize = bufferSize - offsetof(HgfsNotifyEventV4, fileName);
- if (HgfsPackHgfsName(fullPath, nameSize, remainingSize, &hgfsNameSize,
- &reply->fileName)) {
- remainingSize -= hgfsNameSize;
- totalLength = bufferSize - remainingSize;
- } else {
- totalLength = 0;
+ if (!HgfsPackHgfsName(cpFullName,
+ cpFullNameSize,
+ remainingSize,
+ &hgfsNameSize,
+ &reply->fileName)) {
+ /* Name would not fit, drop the event. */
+ free(cpFullName);
+ goto exit;
}
- free(fullPath);
+ remainingSize -= hgfsNameSize;
+ totalLength = bufferSize - remainingSize;
+ free(cpFullName);
} else {
reply->fileName.length = 0;
totalLength = sizeof *reply;
}
+
+exit:
return totalLength;
}
diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerParameters.h b/open-vm-tools/lib/hgfsServer/hgfsServerParameters.h
index fe1d081b..9d0ff756 100644
--- a/open-vm-tools/lib/hgfsServer/hgfsServerParameters.h
+++ b/open-vm-tools/lib/hgfsServer/hgfsServerParameters.h
@@ -246,7 +246,7 @@ HgfsUnpackSearchOpenRequest(const void *packet, // IN: HGFS packet
size_t packetSize, // IN: request packet size
HgfsOp op, // IN: request type
const char **dirName, // OUT: directory name
- uint32 *dirNameLength, // OUT: name length
+ size_t *dirNameLength, // OUT: name length
uint32 *caseFlags); // OUT: case flags
Bool
HgfsPackCloseReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
diff --git a/open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuest.c b/open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuest.c
index d71315f8..9ba9d979 100644
--- a/open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuest.c
+++ b/open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuest.c
@@ -78,7 +78,7 @@
* also removed and the HGFS server exit is called and this object is torn down.
*/
typedef struct HgfsChannelServerData {
- HgfsServerSessionCallbacks *serverCBTable; /* HGFS server entry points. */
+ HgfsServerCallbacks *serverCBTable; /* HGFS server entry points. */
Atomic_uint32 refCount; /* Server data reference count. */
} HgfsChannelServerData;
@@ -197,7 +197,8 @@ HgfsChannelPutServer(HgfsChannelServerData *serverInfo) // IN/OUT: ref count
*/
static Bool
-HgfsChannelInitServer(HgfsChannelServerData *serverInfo) // IN/OUT: ref count
+HgfsChannelInitServer(HgfsServerMgrCallbacks *mgrCb, // IN: server manager callbacks
+ HgfsChannelServerData *serverInfo) // IN/OUT: ref count
{
Bool result;
@@ -206,7 +207,7 @@ HgfsChannelInitServer(HgfsChannelServerData *serverInfo) // IN/OUT: ref count
Debug("%s: Initialize Hgfs server.\n", __FUNCTION__);
/* If we have a new connection initialize the server session with default settings. */
- result = HgfsServer_InitState(&serverInfo->serverCBTable, &gHgfsGuestCfgSettings, NULL);
+ result = HgfsServer_InitState(&serverInfo->serverCBTable, &gHgfsGuestCfgSettings, mgrCb);
if (!result) {
Debug("%s: Could not init Hgfs server.\n", __FUNCTION__);
}
@@ -343,6 +344,7 @@ HgfsChannelPutChannel(HgfsChannelData *channel) // IN/OUT: ref count
static Bool
HgfsChannelInitChannel(HgfsChannelData *channel, // IN/OUT: channel object
+ HgfsServerMgrCallbacks *mgrCb, // IN: server manager callbacks
HgfsChannelServerData *serverInfo) // IN/OUT: server info
{
Bool result = TRUE;
@@ -360,7 +362,7 @@ HgfsChannelInitChannel(HgfsChannelData *channel, // IN/OUT: channel obj
channel->serverInfo = serverInfo;
if (0 == serverInfoCount) {
/* The HGFS server has not been initialized, do it now. */
- result = HgfsChannelInitServer(channel->serverInfo);
+ result = HgfsChannelInitServer(mgrCb, channel->serverInfo);
if (!result) {
Debug("%s: Could not init Hgfs server.\n", __FUNCTION__);
goto exit;
@@ -431,7 +433,7 @@ HgfsChannelActivateChannel(HgfsChannelData *channel, // IN/OUT: channel object
Bool success = FALSE;
struct HgfsGuestConn *connData = NULL;
- if (channel->ops->init(channel->serverInfo->serverCBTable,
+ if (channel->ops->init(&channel->serverInfo->serverCBTable->session,
rpc,
rpcCallback,
&connData)) {
@@ -579,7 +581,8 @@ HgfsChannelTeardownChannel(HgfsChannelData *channel) // IN/OUT: connection manag
*/
Bool
-HgfsChannelGuest_Init(HgfsServerMgrData *mgrData) // IN/OUT: connection manager object
+HgfsChannelGuest_Init(HgfsServerMgrData *mgrData, // IN/OUT: server manager data
+ HgfsServerMgrCallbacks *mgrCb) // IN: server manager callbacks
{
Bool success = FALSE;
HgfsChannelData *channel = &gHgfsChannels[0]; // Shared channel (internal RPC)
@@ -616,7 +619,7 @@ HgfsChannelGuest_Init(HgfsServerMgrData *mgrData) // IN/OUT: connection manager
if (0 == channelRefCount) {
/* Initialize channels objects. */
- if (!HgfsChannelInitChannel(channel, &gHgfsChannelServerInfo)) {
+ if (!HgfsChannelInitChannel(channel, mgrCb, &gHgfsChannelServerInfo)) {
Debug("%s: Could not init channel.\n", __FUNCTION__);
goto exit;
}
diff --git a/open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuestInt.h b/open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuestInt.h
index b27a216b..3d9f633b 100644
--- a/open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuestInt.h
+++ b/open-vm-tools/lib/hgfsServerManagerGuest/hgfsChannelGuestInt.h
@@ -51,7 +51,7 @@ typedef struct HgfsGuestChannelCBTable {
extern HgfsGuestChannelCBTable gGuestBackdoorOps;
/* For use by HgfsServerManager. */
-Bool HgfsChannelGuest_Init(HgfsServerMgrData *data);
+Bool HgfsChannelGuest_Init(HgfsServerMgrData *data, HgfsServerMgrCallbacks *cb);
void HgfsChannelGuest_Exit(HgfsServerMgrData *data);
Bool HgfsChannelGuest_Receive(HgfsServerMgrData *data,
char const *packetIn,
diff --git a/open-vm-tools/lib/hgfsServerManagerGuest/hgfsServerManagerGuest.c b/open-vm-tools/lib/hgfsServerManagerGuest/hgfsServerManagerGuest.c
index 4184dbbc..0e9f3275 100644
--- a/open-vm-tools/lib/hgfsServerManagerGuest/hgfsServerManagerGuest.c
+++ b/open-vm-tools/lib/hgfsServerManagerGuest/hgfsServerManagerGuest.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2006-2015 VMware, Inc. All rights reserved.
+ * Copyright (C) 2006,2014-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -25,6 +25,7 @@
*
*/
+#include <string.h>
#include "hgfsServerPolicy.h"
#include "hgfsChannelGuestInt.h"
#include "hgfsServerManager.h"
@@ -32,7 +33,15 @@
#include "vm_assert.h"
#include "hgfs.h"
-
+/*
+ * Local for now and will be used in conjuncutntion with the manager data passed
+ * on registration.
+ */
+static HgfsServerMgrCallbacks gHgfsServerManagerGuestData = {
+ {
+ NULL, // Filled by the policy manager
+ }
+};
/*
*----------------------------------------------------------------------------
@@ -89,18 +98,20 @@ HgfsServerManager_Register(HgfsServerMgrData *data) // IN: RpcIn channel
ASSERT(data);
ASSERT(data->appName);
-
-
/*
* Passing NULL here is safe because the shares maintained by the guest
* policy server never change, invalidating the need for an invalidate
* function.
+ * XXX - retrieve the enum of shares routines and will need to pass this
+ * down through the channel guest into the HGFS server directly.
*/
- if (!HgfsServerPolicy_Init(NULL, NULL)) {
+ if (!HgfsServerPolicy_Init(NULL,
+ NULL,
+ &gHgfsServerManagerGuestData.enumResources)) {
return FALSE;
}
- if (!HgfsChannelGuest_Init(data)) {
+ if (!HgfsChannelGuest_Init(data, &gHgfsServerManagerGuestData)) {
HgfsServerPolicy_Cleanup();
return FALSE;
}
@@ -160,4 +171,5 @@ HgfsServerManager_Unregister(HgfsServerMgrData *data) // IN: RpcIn chann
HgfsChannelGuest_Exit(data);
HgfsServerPolicy_Cleanup();
+ memset(&gHgfsServerManagerGuestData, 0, sizeof gHgfsServerManagerGuestData);
}
diff --git a/open-vm-tools/lib/hgfsServerPolicyGuest/hgfsServerPolicyGuest.c b/open-vm-tools/lib/hgfsServerPolicyGuest/hgfsServerPolicyGuest.c
index c043c6f3..470c5a54 100644
--- a/open-vm-tools/lib/hgfsServerPolicyGuest/hgfsServerPolicyGuest.c
+++ b/open-vm-tools/lib/hgfsServerPolicyGuest/hgfsServerPolicyGuest.c
@@ -48,6 +48,16 @@ typedef struct HgfsServerPolicyState {
static HgfsServerPolicyState myState;
+static void *
+HgfsServerPolicyEnumSharesInit(void);
+static Bool
+HgfsServerPolicyEnumSharesGet(void *data,
+ char const **name,
+ size_t *len,
+ Bool *done);
+static Bool
+HgfsServerPolicyEnumSharesExit(void *data);
+
/*
*-----------------------------------------------------------------------------
@@ -125,16 +135,18 @@ HgfsServerPolicyDestroyShares(DblLnkLst_Links *head) // IN
*/
Bool
-HgfsServerPolicy_Init(HgfsInvalidateObjectsFunc *invalidateObjects, // Unused
- HgfsRegisterSharedFolderFunc *registerFolder) // Unused
+HgfsServerPolicy_Init(HgfsInvalidateObjectsFunc invalidateObjects, // Unused
+ HgfsRegisterSharedFolderFunc registerFolder, // Unused
+ HgfsServerResEnumCallbacks *enumResources) // OUT enum callbacks
{
HgfsSharedFolder *rootShare;
/*
- * We do not recognize this callback, so make sure our caller doesn't pass
+ * Currently these callbacks are not used, so make sure our caller doesn't pass
* it in.
*/
- ASSERT(!invalidateObjects);
+ ASSERT(invalidateObjects == NULL);
+ ASSERT(registerFolder == NULL);
DblLnkLst_Init(&myState.shares);
@@ -165,6 +177,13 @@ HgfsServerPolicy_Init(HgfsInvalidateObjectsFunc *invalidateObjects, // Unused
/* Add the root node to the end of the list */
DblLnkLst_LinkLast(&myState.shares, &rootShare->links);
+ /*
+ * Fill the share enumeration callback table.
+ */
+ enumResources->init = HgfsServerPolicyEnumSharesInit;
+ enumResources->get = HgfsServerPolicyEnumSharesGet;
+ enumResources->exit = HgfsServerPolicyEnumSharesExit;
+
return TRUE;
}
@@ -280,7 +299,7 @@ HgfsServerPolicyGetShare(HgfsServerPolicyState *state, // IN
}
-/* State used by HgfsServerPolicy_GetShares and friends */
+/* State used by HgfsServerPolicyEnumSharesGet and friends */
typedef struct State {
DblLnkLst_Links *next;
} GetSharesState;
@@ -289,9 +308,9 @@ typedef struct State {
/*
*-----------------------------------------------------------------------------
*
- * HgfsServerPolicy_GetSharesInit --
+ * HgfsServerPolicyEnumSharesInit --
*
- * Setup state for HgfsServerPolicy_GetShares
+ * Setup state for HgfsServerPolicyEnumSharesGet
*
* Results:
* Pointer to state on success.
@@ -303,14 +322,14 @@ typedef struct State {
*-----------------------------------------------------------------------------
*/
-void *
-HgfsServerPolicy_GetSharesInit(void)
+static void *
+HgfsServerPolicyEnumSharesInit(void)
{
GetSharesState *that;
that = malloc(sizeof *that);
if (!that) {
- LOG(4, ("HgfsServerPolicy_GetSharesInit: couldn't allocate state\n"));
+ LOG(4, ("HgfsServerPolicyEnumSharesInit: couldn't allocate state\n"));
return NULL;
}
@@ -322,14 +341,14 @@ HgfsServerPolicy_GetSharesInit(void)
/*
*-----------------------------------------------------------------------------
*
- * HgfsServerPolicy_GetShares --
+ * HgfsServerPolicyEnumSharesGet --
*
* Enumerate share names one at a time.
*
* When finished, sets "done" to TRUE.
*
* Should be called with the results obtained by calling
- * HgfsServerPolicy_GetSharesInit.
+ * HgfsServerPolicyEnumSharesInit.
*
* Results:
* TRUE on success.
@@ -341,11 +360,11 @@ HgfsServerPolicy_GetSharesInit(void)
*-----------------------------------------------------------------------------
*/
-Bool
-HgfsServerPolicy_GetShares(void *data, // IN: Callback data
- char const **name, // OUT: Share name
- size_t *len, // OUT: Name length
- Bool *done) // OUT: Completion status
+static Bool
+HgfsServerPolicyEnumSharesGet(void *data, // IN: Callback data
+ char const **name, // OUT: Share name
+ size_t *len, // OUT: Name length
+ Bool *done) // OUT: Completion status
{
GetSharesState *that;
HgfsSharedFolder *share;
@@ -367,7 +386,7 @@ HgfsServerPolicy_GetShares(void *data, // IN: Callback data
that->next = share->links.next;
*name = share->name;
*len = share->nameLen;
- LOG(4, ("HgfsServerPolicy_GetShares: Share name is \"%s\"\n",
+ LOG(4, ("HgfsServerPolicyEnumSharesGet: Share name is \"%s\"\n",
*name));
*done = FALSE;
return TRUE;
@@ -377,9 +396,9 @@ HgfsServerPolicy_GetShares(void *data, // IN: Callback data
/*
*-----------------------------------------------------------------------------
*
- * HgfsServerPolicy_GetSharesCleanup --
+ * HgfsServerPolicyEnumSharesExit --
*
- * Cleanup state from HgfsServerPolicy_GetShares
+ * Cleanup state from HgfsServerPolicyEnumSharesGet
*
* Results:
* TRUE on success.
@@ -391,8 +410,8 @@ HgfsServerPolicy_GetShares(void *data, // IN: Callback data
*-----------------------------------------------------------------------------
*/
-Bool
-HgfsServerPolicy_GetSharesCleanup(void *data) // IN: Callback data
+static Bool
+HgfsServerPolicyEnumSharesExit(void *data) // IN: Callback data
{
GetSharesState *that;
diff --git a/open-vm-tools/lib/printer/Makefile.am b/open-vm-tools/lib/hgfsUri/Makefile.am
index f0124a58..87060924 100644
--- a/open-vm-tools/lib/printer/Makefile.am
+++ b/open-vm-tools/lib/hgfsUri/Makefile.am
@@ -1,5 +1,5 @@
################################################################################
-### Copyright (C) 2007-2015 VMware, Inc. All rights reserved.
+### Copyright 2015 VMware, Inc. All rights reserved.
###
### This program is free software; you can redistribute it and/or modify
### it under the terms of version 2 of the GNU General Public License as
@@ -15,7 +15,12 @@
### Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
################################################################################
-noinst_LTLIBRARIES = libPrinter.la
+noinst_LTLIBRARIES = libHgfsUri.la
+
+libHgfsUri_la_SOURCES =
+libHgfsUri_la_SOURCES += hgfsUriPosix.c
+
+AM_CFLAGS =
+AM_CFLAGS += -DVMTOOLS_USE_GLIB
+AM_CFLAGS += @GLIB2_CPPFLAGS@
-libPrinter_la_SOURCES =
-libPrinter_la_SOURCES += printer.c
diff --git a/open-vm-tools/lib/hgfsUri/hgfsUriPosix.c b/open-vm-tools/lib/hgfsUri/hgfsUriPosix.c
new file mode 100644
index 00000000..0a375362
--- /dev/null
+++ b/open-vm-tools/lib/hgfsUri/hgfsUriPosix.c
@@ -0,0 +1,110 @@
+/*********************************************************
+ * Copyright (C) 2015 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * hgfsPosix.c --
+ *
+ * Provides a library for guest applications to convert local pathames to
+ * x-vmware-share:// style URIs
+ */
+
+#if !defined __linux__ && !defined __APPLE__ && !defined __FreeBSD__
+# error This file should not be compiled
+#endif
+
+#include "vmware.h"
+#include "debug.h"
+#include "str.h"
+#include <glib.h>
+
+#include "hgfsUri.h"
+#include "hgfsHelper.h"
+
+#include "util.h"
+#include "unicode.h"
+#include "hgfsEscape.h"
+
+#include "ghIntegrationCommon.h" // For GHI_HGFS_SHARE_URL_UTF8
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsUri_ConvertFromPathToHgfsUri --
+ *
+ * Test the UTF8 pathname to see if it's on an HGFS Share. If it is
+ * construct a UTF8 URI in the form of x-vmware-share://share_name/item.txt.
+ * If not, convert to a regular UTF8 URI string.
+ *
+ * Results:
+ * Filename as UTF8 URI string if success, NULL if failed.
+ *
+ * Side effects:
+ * Memory may be allocated for the returned string.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char *
+HgfsUri_ConvertFromPathToHgfsUri(const char *pathName, // IN: path to convert
+ Bool hgfsOnly) // IN
+{
+ char *shareUri = NULL;
+ Bool isHgfsName = FALSE;
+ char *sharesDefaultRootPath = NULL;
+
+ /* We can only operate on full paths. */
+ if (pathName[0] != DIRSEPC) {
+ return shareUri;
+ }
+
+ /* Retrieve the servername & share name in use. */
+ if (!HgfsHlpr_QuerySharesDefaultRootPath(&sharesDefaultRootPath)) {
+ Debug("%s: Unable to query shares default root path\n", __FUNCTION__);
+ goto exit;
+ }
+
+ if (Unicode_StartsWith(pathName, sharesDefaultRootPath)) {
+ char *relativeSharePath = NULL;
+ char *escapedSharePath = NULL;
+ UnicodeIndex relativePathStart = strlen(sharesDefaultRootPath);
+ if ( strlen(pathName) > relativePathStart
+ && pathName[relativePathStart] == DIRSEPC) {
+ relativePathStart++;
+ }
+ relativeSharePath = Unicode_RemoveRange(pathName, 0, relativePathStart);
+ HgfsEscape_Undo(relativeSharePath, strlen(relativeSharePath) + 1);
+ escapedSharePath = g_uri_escape_string(relativeSharePath, "/", FALSE);
+ shareUri = Unicode_Append(GHI_HGFS_SHARE_URL_UTF8, escapedSharePath);
+ g_free(escapedSharePath);
+ free(relativeSharePath);
+ isHgfsName = TRUE;
+ }
+
+exit:
+ if (!isHgfsName && !hgfsOnly) {
+ /* Only convert non-hgfs file name if hgfsOnly is not set. */
+ char *escapedPath = g_uri_escape_string(pathName, "/", FALSE);
+ shareUri = Str_Asprintf(NULL,
+ "file://%s",
+ escapedPath);
+ g_free(escapedPath);
+ }
+ HgfsHlpr_FreeSharesRootPath(sharesDefaultRootPath);
+ return shareUri;
+}
diff --git a/open-vm-tools/lib/include/appUtil.h b/open-vm-tools/lib/include/appUtil.h
index f35bac2d..eb7a97ab 100644
--- a/open-vm-tools/lib/include/appUtil.h
+++ b/open-vm-tools/lib/include/appUtil.h
@@ -26,6 +26,10 @@
#define _APP_UTIL_H_
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
@@ -85,6 +89,7 @@ HICON AppUtil_GetWindowIcon(HWND hwnd,
void AppUtil_BuildGlobalApplicationList(void);
+wchar_t* AppUtil_SanitizeCommandLine(const wchar_t *commandLineUtf16);
char *AppUtil_ActionURIForCommandLine(const WCHAR *commandLineUtf16);
Bool AppUtil_CommandLineForShellCommandURI(const char *shellCommandURI,
char **executablePath,
@@ -112,6 +117,8 @@ Bool AppUtil_GetIconIndexAndLocationForShortcut(const TCHAR *shortcut,
TCHAR *iconFile,
int *iconIndex);
+PISECURITY_DESCRIPTOR AppUtil_AllocateLowIntegritySD(void);
+
LPSTR AppUtil_ToLowerUtf8(LPCSTR s);
LPWSTR AppUtil_ToLowerUtf16(LPCWSTR s);
diff --git a/open-vm-tools/lib/include/asyncsocket.h b/open-vm-tools/lib/include/asyncsocket.h
index e1b4a4d3..9d41a72b 100644
--- a/open-vm-tools/lib/include/asyncsocket.h
+++ b/open-vm-tools/lib/include/asyncsocket.h
@@ -65,6 +65,27 @@
#define ASOCKERR_BIND 10
#define ASOCKERR_BINDADDRINUSE 11
#define ASOCKERR_LISTEN 12
+#define ASOCKERR_CONNECTSSL 13
+
+
+/*
+ * Websocket close status codes --
+ *
+ * enum has numbers in names because RFC6455 refers to the numbers frequently.
+ */
+enum {
+ WEB_SOCKET_CLOSE_STATUS_1000_NORMAL = 1000,
+ WEB_SOCKET_CLOSE_STATUS_1001_GOING_AWAY = 1001,
+ WEB_SOCKET_CLOSE_STATUS_1002_PROTOCOL_ERROR = 1002,
+ WEB_SOCKET_CLOSE_STATUS_1003_INVALID_DATA = 1003,
+ WEB_SOCKET_CLOSE_STATUS_1005_EMPTY = 1005,
+ WEB_SOCKET_CLOSE_STATUS_1006_ABNORMAL = 1006,
+ WEB_SOCKET_CLOSE_STATUS_1007_INCONSISTENT_DATA = 1007,
+ WEB_SOCKET_CLOSE_STATUS_1008_POLICY_VIOLATION = 1008,
+ WEB_SOCKET_CLOSE_STATUS_1009_MESSAGE_TOO_BIG = 1009,
+ WEB_SOCKET_CLOSE_STATUS_1010_UNSUPPORTED_EXTENSIONS = 1010,
+ WEB_SOCKET_CLOSE_STATUS_1015_TLS_HANDSHAKE_ERROR = 1015,
+};
/*
* Flags passed into AsyncSocket_Connect*().
@@ -209,6 +230,7 @@ AsyncSocket *AsyncSocket_ListenVMCI(unsigned int cid,
AsyncSocket *AsyncSocket_ListenWebSocket(const char *addrStr,
unsigned int port,
Bool useSSL,
+ const char *protocols[],
AsyncSocketConnectFn connectFn,
void *clientData,
AsyncSocketPollParams *pollParams,
@@ -216,6 +238,7 @@ AsyncSocket *AsyncSocket_ListenWebSocket(const char *addrStr,
#ifndef _WIN32
AsyncSocket *AsyncSocket_ListenWebSocketUDS(const char *pipeName,
Bool useSSL,
+ const char *protocols[],
AsyncSocketConnectFn connectFn,
void *clientData,
AsyncSocketPollParams *pollParams,
@@ -257,14 +280,16 @@ AsyncSocket_ConnectNamedPipe(char *pipeName,
#endif
#ifndef VMX86_TOOLS
-AsyncSocket *AsyncSocket_ConnectWebSocket(const char *url,
- Bool permitUnverifiedSSL,
- const char *cookies,
- AsyncSocketConnectFn connectFn,
- void *clientData,
- AsyncSocketConnectFlags flags,
- AsyncSocketPollParams *pollParams,
- int *error);
+AsyncSocket *
+AsyncSocket_ConnectWebSocket(const char *url,
+ struct _SSLVerifyParam *sslVerifyParam,
+ const char *cookies,
+ const char *protocols[],
+ AsyncSocketConnectFn connectFn,
+ void *clientData,
+ AsyncSocketConnectFlags flags,
+ AsyncSocketPollParams *pollParams,
+ int *error);
#endif
#ifndef USE_SSL_DIRECT
@@ -272,7 +297,8 @@ AsyncSocket *AsyncSocket_ConnectWebSocket(const char *url,
* Initiate SSL connection on existing asock, with optional cert verification
*/
Bool AsyncSocket_ConnectSSL(AsyncSocket *asock,
- struct _SSLVerifyParam *verifyParam);
+ struct _SSLVerifyParam *verifyParam,
+ void *sslContext);
Bool AsyncSocket_AcceptSSL(AsyncSocket *asock);
#endif
@@ -405,10 +431,21 @@ char *AsyncSocket_GetWebSocketCookie(AsyncSocket *asock);
#endif
/*
+ * Retrieve the close status, if received, for a websocket connection
+ */
+uint16 AsyncSocket_GetWebSocketCloseStatus(const AsyncSocket *asock);
+
+/*
* Set low-latency mode for sends:
*/
void AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock, Bool enable);
+/*
+ * Get negotiated websocket protocol
+ */
+const char *AsyncSocket_GetWebSocketProtocol(AsyncSocket *asock);
+
+const char * stristr(const char *s, const char *find);
/*
* Some logging macros for convenience
diff --git a/open-vm-tools/lib/include/auth.h b/open-vm-tools/lib/include/auth.h
index ca3bdd1d..c6b228e1 100644
--- a/open-vm-tools/lib/include/auth.h
+++ b/open-vm-tools/lib/include/auth.h
@@ -66,7 +66,7 @@ AuthToken Auth_AuthenticateSelf(void);
#endif
-AuthToken Auth_AuthenticateUser(ConstUnicode user, ConstUnicode pass);
+AuthToken Auth_AuthenticateUser(const char *user, const char *pass);
void Auth_CloseToken(AuthToken token);
diff --git a/open-vm-tools/lib/include/backdoor_def.h b/open-vm-tools/lib/include/backdoor_def.h
index 4afaf87e..bdb29b54 100644
--- a/open-vm-tools/lib/include/backdoor_def.h
+++ b/open-vm-tools/lib/include/backdoor_def.h
@@ -118,7 +118,7 @@
//#define BDOOR_CMD_DEVEL_FAKEHARDWARE 44 /* Not in use. */
#define BDOOR_CMD_GETHZ 45
#define BDOOR_CMD_GETTIMEFULL 46
-#define BDOOR_CMD_STATELOGGER 47 /* Disabled by default. */
+//#define BDOOR_CMD_STATELOGGER 47 /* Not in use. */
#define BDOOR_CMD_CHECKFORCEBIOSSETUP 48 /* CPL 0 only. */
#define BDOOR_CMD_LAZYTIMEREMULATION 49 /* CPL 0 only. */
#define BDOOR_CMD_BIOSBBS 50 /* CPL 0 only. */
@@ -145,13 +145,14 @@
# define BDOOR_CMD_FAS_GET_TABLE_SKIP 5
# define BDOOR_CMD_FAS_GET_SLEEP_ENABLES 6
# define BDOOR_CMD_FAS_GET_HARD_RESET_ENABLE 7
-#define BDOOR_CMD_SENDPSHAREHINTS 66
+#define BDOOR_CMD_SENDPSHAREHINTS 66 /* Not in use. Deprecated. */
#define BDOOR_CMD_ENABLE_USB_MOUSE 67
#define BDOOR_CMD_GET_VCPU_INFO 68
# define BDOOR_CMD_VCPU_SLC64 0
# define BDOOR_CMD_VCPU_SYNC_VTSCS 1
# define BDOOR_CMD_VCPU_HV_REPLAY_OK 2
# define BDOOR_CMD_VCPU_LEGACY_X2APIC_OK 3
+# define BDOOR_CMD_VCPU_MMIO_HONORS_PAT 4
# define BDOOR_CMD_VCPU_RESERVED 31
#define BDOOR_CMD_EFI_SERIALCON_CONFIG 69 /* CPL 0 only. */
#define BDOOR_CMD_BUG328986 70 /* CPL 0 only. */
@@ -172,33 +173,30 @@
#define BDOOR_CMD_GET_PCI_BAR 79 /* CPL 0 only */
#define BDOOR_CMD_SHOULD_GENERATE_SYSTEMID 80 /* CPL 0 only */
#define BDOOR_CMD_READ_DEBUG_FILE 81 /* Devel only. */
-#define BDOOR_CMD_MAX 82
+#define BDOOR_CMD_SCREENSHOT 82 /* Devel only. */
+#define BDOOR_CMD_INJECT_KEY 83 /* Devel only. */
+#define BDOOR_CMD_INJECT_MOUSE 84 /* Devel only. */
+#define BDOOR_CMD_MKS_GUEST_STATS 85 /* CPL 0 only. */
+# define BDOOR_CMD_MKSGS_RESET 0
+# define BDOOR_CMD_MKSGS_ADD_PPN 1
+# define BDOOR_CMD_MKSGS_REMOVE_PPN 2
+#define BDOOR_CMD_ABSPOINTER_RESTRICT 86
+#define BDOOR_CMD_GUESTINTEGRITY 87
+# define BDOOR_CMD_GI_SETUP 0
+# define BDOOR_CMD_GI_REMOVE 1
+#define BDOOR_CMD_MKSSTATS_SNAPSHOT 88 /* Devel only. */
+# define BDOOR_CMD_MKSSTATS_START 0
+# define BDOOR_CMD_MKSSTATS_STOP 1
+#define BDOOR_CMD_MAX 89
-/*
+/*
* IMPORTANT NOTE: When modifying the behavior of an existing backdoor command,
* you must adhere to the semantics expected by the oldest Tools who use that
- * command. Specifically, do not alter the way in which the command modifies
+ * command. Specifically, do not alter the way in which the command modifies
* the registers. Otherwise backwards compatibility will suffer.
*/
-/* Processing mode for guest pshare hints (SENDPSHAREHINTS cmd) */
-#define BDOOR_PSHARE_HINTS_ASYNC 0
-#define BDOOR_PSHARE_HINTS_SYNC 1
-
-#define BDOOR_PSHARE_HINTS_TYPE(ecx) (((ecx) >> 16) & 0x1)
-
-/* Version of backdoor pshare hints protocol */
-#define BDOOR_PSHARE_HINTS_VERSION 1
-#define BDOOR_PSHARE_HINTS_VER(ecx) (((ecx) >> 17) & 0x7f)
-
-/* Task applied to backdoor pshare hints */
-#define BDOOR_PSHARE_HINTS_CMD_SHARE 0
-#define BDOOR_PSHARE_HINTS_CMD_DROP 1
-#define BDOOR_PSHARE_HINTS_CMD_MAX 2
-
-#define BDOOR_PSHARE_HINTS_CMD(ecx) (((ecx) >> 24) & 0xff)
-
/* Nesting control operations */
#define NESTING_CONTROL_RESTRICT_BACKDOOR 0
diff --git a/open-vm-tools/lib/include/base64.h b/open-vm-tools/lib/include/base64.h
index b9f2d716..811ee607 100644
--- a/open-vm-tools/lib/include/base64.h
+++ b/open-vm-tools/lib/include/base64.h
@@ -38,9 +38,8 @@ Bool Base64_ChunkDecode(char const *src, size_t inSize,
Bool Base64_ValidEncoding(char const *src, size_t srcLength);
size_t Base64_EncodedLength(uint8 const *src, size_t srcLength);
size_t Base64_DecodedLength(char const *src, size_t srcLength);
-Bool Base64_EasyEncode(const uint8 *src, size_t srcLength,
- char **target);
-Bool Base64_EasyDecode(const char *src,
- uint8 **target, size_t *targSize);
+Bool Base64_EasyEncode(const uint8 *src, size_t srcLength, char **target);
+Bool Base64_EasyDecode(const char *src, uint8 **target, size_t *targSize);
+Bool Base64_DecodeFixed(const char *src, char *outBuf, size_t outBufSize);
#endif
diff --git a/open-vm-tools/lib/include/bsdfmt.h b/open-vm-tools/lib/include/bsdfmt.h
index e9543abd..c341248e 100644
--- a/open-vm-tools/lib/include/bsdfmt.h
+++ b/open-vm-tools/lib/include/bsdfmt.h
@@ -1,5 +1,5 @@
/* **********************************************************
- * Copyright 2008 VMware, Inc. All rights reserved.
+ * Copyright 2008-2014 VMware, Inc. All rights reserved.
* **********************************************************/
/*
diff --git a/open-vm-tools/lib/include/buildNumber.h b/open-vm-tools/lib/include/buildNumber.h
index eb912f92..9862eae2 100644
--- a/open-vm-tools/lib/include/buildNumber.h
+++ b/open-vm-tools/lib/include/buildNumber.h
@@ -1,12 +1,12 @@
#define BUILD_NUMBER \
- "build-2822639"
+ "build-3000743"
#define BUILD_NUMBER_NUMERIC \
- 2822639
+ 3000743
#define BUILD_NUMBER_NUMERIC_STRING \
- "2822639"
+ "3000743"
#define PRODUCT_BUILD_NUMBER \
- "product-build-48224"
+ "product-build-50046"
#define PRODUCT_BUILD_NUMBER_NUMERIC \
- 48224
+ 50046
#define PRODUCT_BUILD_NUMBER_NUMERIC_STRING \
- "48224"
+ "50046"
diff --git a/open-vm-tools/lib/include/clamped.h b/open-vm-tools/lib/include/clamped.h
index a36c07d7..8d7e99fc 100644
--- a/open-vm-tools/lib/include/clamped.h
+++ b/open-vm-tools/lib/include/clamped.h
@@ -46,55 +46,11 @@
/*
- *----------------------------------------------------------------------
- *
- * Clamped_SAdd32 --
- *
- * Signed 32-bit addition.
- *
- * Add two integers, clamping the result to MAX_INT32 or
- * MIN_INT32 if it would have overflowed.
- *
- * Results:
- * On success, returns TRUE.
- * If the result would have overflowed and we clamped it, returns FALSE.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static INLINE Bool
-Clamped_SAdd32(int32 *out, // OUT
- int32 a, // IN
- int32 b) // IN
-{
- int32 result;
-
- result = a + b;
-
- if (UNLIKELY(b > 0 && result < a)) {
- *out = MAX_INT32;
- return FALSE;
- }
-
- if (UNLIKELY(b < 0 && result > a)) {
- *out = MIN_INT32;
- return FALSE;
- }
-
- *out = result;
- return TRUE;
-}
-
-
-/*
*-----------------------------------------------------------------------------
*
* Clamped_U64To32 --
*
- * Convert Unsigned 64-bit to 32-bit, clamping instead of truncating.
+ * Convert unsigned 64-bit to 32-bit, clamping instead of truncating.
*
* Results:
* On success, returns TRUE. If the result would have overflowed
@@ -156,6 +112,35 @@ Clamped_S64To32(int32 *out, // OUT
/*
+ *----------------------------------------------------------------------
+ *
+ * Clamped_SAdd32 --
+ *
+ * Signed 32-bit addition.
+ *
+ * Add two integers, clamping the result to MAX_INT32 or
+ * MIN_INT32 if it would have overflowed.
+ *
+ * Results:
+ * On success, returns TRUE.
+ * If the result would have overflowed and we clamped it, returns FALSE.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE Bool
+Clamped_SAdd32(int32 *out, // OUT
+ int32 a, // IN
+ int32 b) // IN
+{
+ return Clamped_S64To32(out, (int64)a + b);
+}
+
+
+/*
*-----------------------------------------------------------------------------
*
* Clamped_UMul32 --
diff --git a/open-vm-tools/lib/include/codeset.h b/open-vm-tools/lib/include/codeset.h
index 6e48f7b9..a039d83c 100644
--- a/open-vm-tools/lib/include/codeset.h
+++ b/open-vm-tools/lib/include/codeset.h
@@ -313,31 +313,31 @@ Bool
CodeSet_Utf16leToUtf8(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut); // OUT
+ size_t *sizeOut); // OUT/OPT
Bool
CodeSet_Utf8ToUtf16le(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut); // OUT
+ size_t *sizeOut); // OUT/OPT
Bool
CodeSet_CurrentToUtf16le(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut); // OUT
+ size_t *sizeOut); // OUT/OPT
Bool
CodeSet_Utf16leToCurrent(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut); // OUT
+ size_t *sizeOut); // OUT/OPT
Bool
CodeSet_Utf16beToCurrent(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut); // OUT
+ size_t *sizeOut); // OUT/OPT
Bool
CodeSetOld_Utf8Normalize(const char *bufIn, // IN
@@ -349,39 +349,39 @@ Bool
CodeSet_Utf8FormDToUtf8FormC(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut); // OUT
+ size_t *sizeOut); // OUT/OPT
Bool
CodeSet_Utf8FormCToUtf8FormD(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut); // OUT
+ size_t *sizeOut); // OUT/OPT
const char *
CodeSet_GetCurrentCodeSet(void);
Bool
-CodeSet_IsEncodingSupported(const char *name);
+CodeSet_IsEncodingSupported(const char *name); // IN:
Bool
CodeSet_Validate(const char *buf, // IN: the string
size_t size, // IN: length of string
const char *code); // IN: encoding
-Bool CodeSet_UTF8ToUTF32(const char *utf8,
- char **utf32);
+Bool CodeSet_UTF8ToUTF32(const char *utf8, // IN:
+ char **utf32); // OUT:
-Bool CodeSet_UTF32ToUTF8(const char *utf32,
- char **utf8);
+Bool CodeSet_UTF32ToUTF8(const char *utf32, // IN:
+ char **utf8); // OUT:
-int CodeSet_LengthInCodePoints(const char *utf8);
+int CodeSet_LengthInCodePoints(const char *utf8); // IN:
-int CodeSet_CodePointOffsetToByteOffset(const char *utf8,
- int codePointOffset);
+int CodeSet_CodePointOffsetToByteOffset(const char *utf8, // IN:
+ int codePointOffset); // IN:
-int CodeSet_GetUtf8(const char *string,
- const char *end,
- uint32 *uchar);
+int CodeSet_GetUtf8(const char *string, // IN:
+ const char *end, // IN:
+ uint32 *uchar); // OUT/OPT:
/*
diff --git a/open-vm-tools/lib/include/conf.h b/open-vm-tools/lib/include/conf.h
index de980b91..60187c79 100644
--- a/open-vm-tools/lib/include/conf.h
+++ b/open-vm-tools/lib/include/conf.h
@@ -50,7 +50,7 @@
#define CONFNAME_SUSPENDSCRIPT "suspend-script"
#define CONFNAME_LOG "log"
#define CONFNAME_LOGFILE "log.file"
-#define CONFNAME_LOGLEVEL "log.level"
+#define CONFNAME_LOGLEVEL "log.level"
#define CONFNAME_DISABLETOOLSVERSION "disable-tools-version"
#define CONFNAME_DISABLEPMTIMERWARNING "disable-pmtimerwarning"
@@ -87,6 +87,21 @@
*/
#define CONFNAME_GUESTINFO_POLLINTERVAL "poll-interval"
+/**
+ * Define a custom GuestStats poll interval (in seconds).
+ *
+ * @note Illegal values result in a @c g_warning and fallback to the default
+ * stats interval.
+ *
+ * @param int User-defined poll interval for stats. Set to 0 to disable polling.
+ */
+#define CONFNAME_GUESTINFO_STATSINTERVAL "stats-interval"
+
+/**
+ * Indicates whether stat results should be written to the log.
+ */
+#define CONFNAME_GUESTINFO_ENABLESTATLOGGING "enable-stat-logging"
+
/*
* END GuestInfo goodies.
******************************************************************************
@@ -104,11 +119,6 @@
#define CONFGROUPNAME_UNITY "unity"
/**
- * Lets users enable debug info from Unity.
- */
-#define CONFNAME_UNITY_ENABLEDEBUG "debug"
-
-/**
* Lets users override system decisions about whether unity should be available.
*/
#define CONFNAME_UNITY_FORCEENABLE "forceEnable"
@@ -140,6 +150,6 @@
#define CONF_VMWARE_TOOLS_REGKEY "Software\\VMware, Inc.\\VMware Tools"
/* Wait 5 seconds between polls to see if the conf file has changed */
-#define CONF_POLL_TIME 500
+#define CONF_POLL_TIME 5
#endif /* __CONF_H__ */
diff --git a/open-vm-tools/lib/include/dbllnklst.h b/open-vm-tools/lib/include/dbllnklst.h
index 95745826..2037dcdb 100644
--- a/open-vm-tools/lib/include/dbllnklst.h
+++ b/open-vm-tools/lib/include/dbllnklst.h
@@ -115,7 +115,7 @@ typedef struct DblLnkLst_Links {
*/
static INLINE void
-DblLnkLst_Init(DblLnkLst_Links *l) // IN
+DblLnkLst_Init(DblLnkLst_Links *l) // OUT
{
l->prev = l->next = l;
}
@@ -141,8 +141,8 @@ DblLnkLst_Init(DblLnkLst_Links *l) // IN
*/
static INLINE void
-DblLnkLst_Link(DblLnkLst_Links *l1, // IN
- DblLnkLst_Links *l2) // IN
+DblLnkLst_Link(DblLnkLst_Links *l1, // IN/OUT
+ DblLnkLst_Links *l2) // IN/OUT
{
DblLnkLst_Links *tmp;
@@ -175,8 +175,8 @@ DblLnkLst_Link(DblLnkLst_Links *l1, // IN
*/
static INLINE void
-DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN
- DblLnkLst_Links *l2) // IN
+DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN/OUT
+ DblLnkLst_Links *l2) // IN/OUT
{
DblLnkLst_Links *tmp;
@@ -203,7 +203,7 @@ DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN
*/
static INLINE void
-DblLnkLst_Unlink1(DblLnkLst_Links *l) // IN
+DblLnkLst_Unlink1(DblLnkLst_Links *l) // IN/OUT
{
DblLnkLst_Unlink(l, l->next);
}
@@ -253,8 +253,8 @@ DblLnkLst_IsLinked(DblLnkLst_Links const *l) // IN
*/
static INLINE void
-DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN
- DblLnkLst_Links *l) // IN
+DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN/OUT
+ DblLnkLst_Links *l) // IN/OUT
{
DblLnkLst_Link(head->next, l);
}
@@ -277,8 +277,8 @@ DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN
*/
static INLINE void
-DblLnkLst_LinkLast(DblLnkLst_Links *head, // IN
- DblLnkLst_Links *l) // IN
+DblLnkLst_LinkLast(DblLnkLst_Links *head, // IN/OUT
+ DblLnkLst_Links *l) // IN/OUT
{
DblLnkLst_Link(head, l);
}
diff --git a/open-vm-tools/lib/include/dictll.h b/open-vm-tools/lib/include/dictll.h
index 91cdd3d8..db0767ac 100644
--- a/open-vm-tools/lib/include/dictll.h
+++ b/open-vm-tools/lib/include/dictll.h
@@ -49,7 +49,7 @@ DictLL_UnmarshalLine(const char *buf, // IN
Bool
DictLL_MarshalLine(DynBuf *output, // IN/OUT
- char const *name, // IN
+ char const *name, // IN/OPT
char const *value); // IN
diff --git a/open-vm-tools/lib/include/dynbuf.h b/open-vm-tools/lib/include/dynbuf.h
index c06bd53e..9b626d2a 100644
--- a/open-vm-tools/lib/include/dynbuf.h
+++ b/open-vm-tools/lib/include/dynbuf.h
@@ -31,14 +31,14 @@
typedef struct DynBuf {
- char *data;
- size_t size;
- size_t allocated;
+ char *data;
+ size_t size;
+ size_t allocated;
} DynBuf;
void
-DynBuf_Init(DynBuf *b); // IN
+DynBuf_Init(DynBuf *b); // OUT
void
DynBuf_Destroy(DynBuf *b); // IN
@@ -52,26 +52,26 @@ DynBuf_Attach(DynBuf *b, // IN
void *data); // IN
void *
-DynBuf_Detach(DynBuf *b); // IN
+DynBuf_Detach(DynBuf *b); // IN/OUT
Bool
-DynBuf_Enlarge(DynBuf *b, // IN
+DynBuf_Enlarge(DynBuf *b, // IN/OUT
size_t min_size); // IN
Bool
-DynBuf_Append(DynBuf *b, // IN
+DynBuf_Append(DynBuf *b, // IN/OUT
void const *data, // IN
size_t size); // IN
Bool
-DynBuf_Trim(DynBuf *b); // IN
+DynBuf_Trim(DynBuf *b); // IN/OUT
Bool
DynBuf_Copy(DynBuf *src, // IN
DynBuf *dest); // OUT
void
-DynBuf_SafeInternalAppend(DynBuf *b, // IN
+DynBuf_SafeInternalAppend(DynBuf *b, // IN/OUT
void const *data, // IN
size_t size, // IN
char const *file, // IN
@@ -160,7 +160,7 @@ static void
#else
static INLINE void
#endif
-DynBuf_SetSize(DynBuf *b, // IN
+DynBuf_SetSize(DynBuf *b, // IN/OUT:
size_t size) // IN
{
ASSERT(b);
@@ -223,7 +223,7 @@ static Bool
#else
static INLINE Bool
#endif
-DynBuf_AppendString(DynBuf *buf, // IN
+DynBuf_AppendString(DynBuf *buf, // IN/OUT
const char *string) // IN
{
/*
diff --git a/open-vm-tools/lib/include/escape.h b/open-vm-tools/lib/include/escape.h
index 112a525d..d94628c9 100644
--- a/open-vm-tools/lib/include/escape.h
+++ b/open-vm-tools/lib/include/escape.h
@@ -47,6 +47,13 @@ Escape_Undo(char escByte, // IN
size_t sizeIn, // IN
size_t *sizeOut); // OUT/OPT
+Bool
+Escape_UndoFixed(char escByte, // IN
+ void const *bufIn, // IN
+ size_t sizeIn, // IN
+ void *bufOut, // IN/OUT
+ size_t bufOutSize); // IN
+
const char *
Escape_Strchr(char escByte, // IN
const char *bufIn, // IN
diff --git a/open-vm-tools/lib/include/file.h b/open-vm-tools/lib/include/file.h
index db60e688..b7bdf1be 100644
--- a/open-vm-tools/lib/include/file.h
+++ b/open-vm-tools/lib/include/file.h
@@ -60,7 +60,7 @@ extern "C"{
*/
typedef struct WalkDirContextImpl WalkDirContextImpl;
-typedef const WalkDirContextImpl *WalkDirContext;
+typedef WalkDirContextImpl *WalkDirContext;
/*
* When File_MakeTempEx2 is called, it creates a temporary file or a directory
@@ -81,8 +81,8 @@ typedef const WalkDirContextImpl *WalkDirContext;
*
*/
-typedef Unicode File_MakeTempCreateNameFunc(uint32 num,
- void *data);
+typedef char *File_MakeTempCreateNameFunc(uint32 num,
+ void *data);
#if defined(__APPLE__)
typedef enum {
@@ -115,17 +115,17 @@ Bool FileMacOS_MakeSecureLibraryCopies(const char *inDir,
#elif defined VMX86_SERVER
struct FS_PartitionListResult;
-int File_GetVMFSAttributes(ConstUnicode pathName,
+int File_GetVMFSAttributes(const char *pathName,
struct FS_PartitionListResult **fsAttrs);
-int File_GetVMFSFSType(ConstUnicode pathName,
+int File_GetVMFSFSType(const char *pathName,
int fd,
uint16 *fsTypeNum);
-int File_GetVMFSVersion(ConstUnicode pathName,
+int File_GetVMFSVersion(const char *pathName,
uint32 *versionNum);
-int File_GetVMFSBlockSize(ConstUnicode pathName,
+int File_GetVMFSBlockSize(const char *pathName,
uint32 *blockSize);
-int File_GetVMFSMountInfo(ConstUnicode pathName,
+int File_GetVMFSMountInfo(const char *pathName,
char **fsType,
uint32 *version,
char **remoteIP,
@@ -133,141 +133,144 @@ int File_GetVMFSMountInfo(ConstUnicode pathName,
char **localMountPoint);
#endif
-Bool File_SupportsZeroedThick(ConstUnicode pathName);
+Bool File_SupportsZeroedThick(const char *pathName);
-Bool File_SupportsMultiWriter(ConstUnicode pathName);
+Bool File_SupportsMultiWriter(const char *pathName);
-Bool File_SupportsMandatoryLock(ConstUnicode pathName);
+Bool File_SupportsMandatoryLock(const char *pathName);
-Bool File_Exists(ConstUnicode pathName);
+Bool File_Exists(const char *pathName);
-int File_Unlink(ConstUnicode pathName);
+int File_Unlink(const char *pathName);
-int File_UnlinkIfExists(ConstUnicode pathName);
+int File_UnlinkIfExists(const char *pathName);
-int File_UnlinkDelayed(ConstUnicode pathName);
+int File_UnlinkDelayed(const char *pathName);
-int File_UnlinkNoFollow(ConstUnicode pathName);
+int File_UnlinkNoFollow(const char *pathName);
-void File_SplitName(ConstUnicode pathName,
- Unicode *volume,
- Unicode *dir,
- Unicode *base);
+void File_SplitName(const char *pathName,
+ char **volume,
+ char **dir,
+ char **base);
-void File_GetPathName(ConstUnicode fullPath,
- Unicode *pathName,
- Unicode *base);
+void File_GetPathName(const char *fullPath,
+ char **pathName,
+ char **base);
-Unicode File_StripSlashes(ConstUnicode path);
+char *File_StripSlashes(const char *path);
-Unicode File_PathJoin(ConstUnicode dirName,
- ConstUnicode baseName);
+char *File_PathJoin(const char *dirName,
+ const char *baseName);
-Bool File_CreateDirectory(ConstUnicode pathName);
+Bool File_CreateDirectory(const char *pathName);
-Bool File_CreateDirectoryEx(ConstUnicode pathName, int mask);
+Bool File_CreateDirectoryEx(const char *pathName,
+ int mask);
-Bool File_EnsureDirectory(ConstUnicode pathName);
+Bool File_EnsureDirectory(const char *pathName);
-Bool File_DeleteEmptyDirectory(ConstUnicode pathName);
+Bool File_DeleteEmptyDirectory(const char *pathName);
-Bool File_CreateDirectoryHierarchy(ConstUnicode pathName,
- Unicode *topmostCreated);
+Bool File_CreateDirectoryHierarchy(const char *pathName,
+ char **topmostCreated);
-Bool File_CreateDirectoryHierarchyEx(ConstUnicode pathName,
+Bool File_CreateDirectoryHierarchyEx(const char *pathName,
int mask,
- Unicode *topmostCreated);
+ char **topmostCreated);
-Bool File_DeleteDirectoryTree(ConstUnicode pathName);
+Bool File_DeleteDirectoryContent(const char *pathName);
-int File_ListDirectory(ConstUnicode pathName,
- Unicode **ids);
+Bool File_DeleteDirectoryTree(const char *pathName);
-Bool File_IsOsfsVolumeEmpty(ConstUnicode pathName);
+int File_ListDirectory(const char *pathName,
+ char ***ids);
+
+Bool File_IsOsfsVolumeEmpty(const char *pathName);
/*
* Simple file-system walk.
*/
-WalkDirContext File_WalkDirectoryStart(ConstUnicode parentPath);
+WalkDirContext File_WalkDirectoryStart(const char *parentPath);
Bool File_WalkDirectoryNext(WalkDirContext context,
- Unicode *path);
+ char **path);
void File_WalkDirectoryEnd(WalkDirContext context);
-Bool File_IsDirectory(ConstUnicode pathName);
+Bool File_IsDirectory(const char *pathName);
-Bool File_IsFile(ConstUnicode pathName);
+Bool File_IsFile(const char *pathName);
-Bool File_IsSymLink(ConstUnicode pathName);
+Bool File_IsSymLink(const char *pathName);
-Bool File_IsCharDevice(ConstUnicode pathName);
+Bool File_IsCharDevice(const char *pathName);
-Bool File_GetParent(Unicode *canPath);
+Bool File_GetParent(char **canPath);
-Bool File_IsRemote(ConstUnicode pathName);
+Bool File_IsRemote(const char *pathName);
-Bool File_IsEmptyDirectory(ConstUnicode pathName);
+Bool File_IsEmptyDirectory(const char *pathName);
-Unicode File_Cwd(ConstUnicode drive); // XXX belongs to `process' module
+char *File_Cwd(const char *drive); // XXX belongs to `process' module
-Unicode File_FullPath(ConstUnicode pathName);
+char *File_FullPath(const char *pathName);
-Bool File_IsFullPath(ConstUnicode pathName);
+Bool File_IsFullPath(const char *pathName);
-uint64 File_GetFreeSpace(ConstUnicode pathName,
+uint64 File_GetFreeSpace(const char *pathName,
Bool doNotAscend);
-uint64 File_GetCapacity(ConstUnicode pathName);
+uint64 File_GetCapacity(const char *pathName);
-int File_MakeTempEx(ConstUnicode dir,
- ConstUnicode pathName,
- Unicode *presult);
+int File_MakeTempEx(const char *dir,
+ const char *pathName,
+ char **presult);
-int File_MakeTempEx2(ConstUnicode dir,
+int File_MakeTempEx2(const char *dir,
Bool createTempFile,
File_MakeTempCreateNameFunc *createNameFunc,
void *createFuncData,
- Unicode *presult);
+ char **presult);
-Unicode File_MakeSafeTempDir(ConstUnicode prefix);
+char *File_MakeSafeTempDir(const char *prefix);
-int64 File_GetModTime(ConstUnicode pathName);
+int64 File_GetModTime(const char *pathName);
-char *File_GetModTimeString(ConstUnicode pathName);
+char *File_GetModTimeString(const char *pathName);
char *File_GetUniqueFileSystemID(const char *pathName);
#ifdef _WIN32
-Unicode File_GetVolumeGUID(ConstUnicode pathName);
+char *File_GetVolumeGUID(const char *pathName);
#endif
-Bool File_GetTimes(ConstUnicode pathName,
+Bool File_GetTimes(const char *pathName,
VmTimeType *createTime,
VmTimeType *accessTime,
VmTimeType *writeTime,
VmTimeType *attrChangeTime);
-Bool File_SetTimes(ConstUnicode pathName,
+Bool File_SetTimes(const char *pathName,
VmTimeType createTime,
VmTimeType accessTime,
VmTimeType writeTime,
VmTimeType attrChangeTime);
-Bool File_GetFilePermissions(ConstUnicode pathName,
+Bool File_GetFilePermissions(const char *pathName,
int *mode);
-Bool File_SetFilePermissions(ConstUnicode pathName,
+Bool File_SetFilePermissions(const char *pathName,
int mode);
-Bool File_SupportsFileSize(ConstUnicode pathName,
+Bool File_SupportsFileSize(const char *pathName,
uint64 fileSize);
-Bool File_GetMaxFileSize(ConstUnicode pathName,
+Bool File_GetMaxFileSize(const char *pathName,
uint64 *maxFileSize);
-Bool File_SupportsLargeFiles(ConstUnicode pathName);
+Bool File_SupportsLargeFiles(const char *pathName);
char *File_MapPathPrefix(const char *oldPath,
const char **oldPrefixes,
@@ -277,49 +280,36 @@ char *File_MapPathPrefix(const char *oldPath,
Bool File_CopyFromFdToFd(FileIODescriptor src,
FileIODescriptor dst);
-FileIOResult File_CreatePrompt(FileIODescriptor *file,
- ConstUnicode pathName,
- int access,
- int prompt);
-
Bool File_CopyFromFd(FileIODescriptor src,
- ConstUnicode dstName,
+ const char *dstName,
Bool overwriteExisting);
-Bool File_Copy(ConstUnicode srcName,
- ConstUnicode dstName,
+Bool File_Copy(const char *srcName,
+ const char *dstName,
Bool overwriteExisting);
-Bool File_CopyFromFdToName(FileIODescriptor src,
- ConstUnicode dstName,
- int dstDispose);
-
-Bool File_CopyFromNameToName(ConstUnicode srcName,
- ConstUnicode dstName,
- int dstDispose);
-
-Bool File_MoveTree(ConstUnicode srcName,
- ConstUnicode dstName,
+Bool File_MoveTree(const char *srcName,
+ const char *dstName,
Bool overwriteExisting,
Bool *asMove);
-Bool File_CopyTree(ConstUnicode srcName,
- ConstUnicode dstName,
+Bool File_CopyTree(const char *srcName,
+ const char *dstName,
Bool overwriteExisting,
Bool followSymlinks);
-Bool File_Replace(ConstUnicode oldFile,
- ConstUnicode newFile);
+Bool File_Replace(const char *oldFile,
+ const char *newFile);
-int File_Rename(ConstUnicode oldFile,
- ConstUnicode newFile);
+int File_Rename(const char *oldFile,
+ const char *newFile);
-int File_RenameRetry(ConstUnicode oldFile,
- ConstUnicode newFile,
+int File_RenameRetry(const char *oldFile,
+ const char *newFile,
uint32 msecMaxWaitTime);
-Bool File_Move(ConstUnicode oldFile,
- ConstUnicode newFile,
+Bool File_Move(const char *oldFile,
+ const char *newFile,
Bool *asRename);
void File_Rotate(const char *pathName,
@@ -327,7 +317,7 @@ void File_Rotate(const char *pathName,
Bool noRename,
char **newFileName);
-int File_GetFSMountInfo(ConstUnicode pathName,
+int File_GetFSMountInfo(const char *pathName,
char **fsType,
uint32 *version,
char **remoteIP,
@@ -335,19 +325,19 @@ int File_GetFSMountInfo(ConstUnicode pathName,
char **localMountPoint);
/* Get size only for regular file. */
-int64 File_GetSize(ConstUnicode pathName);
+int64 File_GetSize(const char *pathName);
/* Get size for file or directory. */
-int64 File_GetSizeEx(ConstUnicode pathName);
+int64 File_GetSizeEx(const char *pathName);
-int64 File_GetSizeByPath(ConstUnicode pathName);
+int64 File_GetSizeByPath(const char *pathName);
-int64 File_GetSizeAlternate(ConstUnicode pathName);
+int64 File_GetSizeAlternate(const char *pathName);
/* file change notification module */
typedef void (*CbFunction)(void *clientData);
-typedef void (*NotifyCallback)(ConstUnicode pathName,
+typedef void (*NotifyCallback)(const char *pathName,
int err,
void *data);
@@ -365,24 +355,24 @@ void File_PollExit(void);
void File_PollImpersonateOnCheck(Bool check);
-Bool File_PollAddFile(ConstUnicode pathName,
+Bool File_PollAddFile(const char *pathName,
uint32 pollPeriod,
NotifyCallback callback,
void *data,
Bool fPeriodic);
-Bool File_PollAddDirFile(ConstUnicode pathName,
+Bool File_PollAddDirFile(const char *pathName,
uint32 pollPeriod,
NotifyCallback callback,
void *data,
Bool fPeriodic);
-Bool File_PollRemoveFile(ConstUnicode pathName,
+Bool File_PollRemoveFile(const char *pathName,
uint32 pollPeriod,
NotifyCallback callback);
-Bool File_IsSameFile(ConstUnicode path1,
- ConstUnicode path2);
+Bool File_IsSameFile(const char *path1,
+ const char *path2);
char *File_PrependToPath(const char *searchPath,
const char *elem);
@@ -392,23 +382,23 @@ Bool File_FindFileInSearchPath(const char *file,
const char *cwd,
char **result);
-Unicode File_ReplaceExtension(ConstUnicode pathName,
- ConstUnicode newExtension,
- uint32 numExtensions,
- ...);
+char *File_ReplaceExtension(const char *pathName,
+ const char *newExtension,
+ uint32 numExtensions,
+ ...);
-Unicode File_RemoveExtension(ConstUnicode pathName);
+char *File_RemoveExtension(const char *pathName);
-Bool File_MakeCfgFileExecutable(ConstUnicode pathName);
+Bool File_MakeCfgFileExecutable(const char *pathName);
char *File_ExpandAndCheckDir(const char *dirName);
char *File_GetSafeTmpDir(Bool useConf);
-int File_MakeSafeTemp(ConstUnicode tag,
- Unicode *presult);
+int File_MakeSafeTemp(const char *tag,
+ char **presult);
-Bool File_DoesVolumeSupportAcls(ConstUnicode pathName);
+Bool File_DoesVolumeSupportAcls(const char *pathName);
#ifdef __cplusplus
} // extern "C" {
diff --git a/open-vm-tools/lib/include/fileIO.h b/open-vm-tools/lib/include/fileIO.h
index 1c26ed23..93b9328d 100644
--- a/open-vm-tools/lib/include/fileIO.h
+++ b/open-vm-tools/lib/include/fileIO.h
@@ -36,6 +36,10 @@
#ifndef _FILEIO_H_
#define _FILEIO_H_
+#ifdef __cplusplus
+extern "C"{
+#endif
+
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
@@ -61,7 +65,7 @@ struct FileLockToken;
typedef struct FileIODescriptor {
HANDLE win32;
uint32 flags;
- Unicode fileName;
+ char *fileName;
struct FileLockToken *lockToken;
} FileIODescriptor;
@@ -70,7 +74,7 @@ typedef struct FileIODescriptor {
typedef struct FileIODescriptor {
int posix;
int flags;
- Unicode fileName;
+ char *fileName;
struct FileLockToken *lockToken;
} FileIODescriptor;
@@ -148,10 +152,6 @@ typedef enum {
*/
#define FILEIO_OPEN_MULTIWRITER_LOCK (1 << 14)
/*
- * Flag the file to be cached by the vBlob caching layer
- */
-#define FILEIO_OPEN_USE_AIO_CACHE (1 << 15)
-/*
* Valid only for MacOS. It eventually results into O_EXLOCK flag passed to open
* system call.
*
@@ -296,18 +296,18 @@ void FileIO_Invalidate(FileIODescriptor *file);
Bool FileIO_IsValid(const FileIODescriptor *fd);
FileIOResult FileIO_Create(FileIODescriptor *file,
- ConstUnicode pathName,
+ const char *pathName,
int access,
FileIOOpenAction action,
int mode);
FileIOResult FileIO_Open(FileIODescriptor *file,
- ConstUnicode pathName,
+ const char *pathName,
int access,
FileIOOpenAction action);
FileIOResult FileIO_OpenRetry(FileIODescriptor *file,
- ConstUnicode pathName,
+ const char *pathName,
int access,
FileIOOpenAction action,
uint32 msecMaxWaitTime);
@@ -326,7 +326,7 @@ FileIOResult FileIO_Write(FileIODescriptor *file,
size_t requested,
size_t *actual);
-Unicode FileIO_AtomicTempPath(ConstUnicode path);
+char *FileIO_AtomicTempPath(const char *path);
FileIOResult FileIO_AtomicTempFile(FileIODescriptor *fileFD,
FileIODescriptor *tempFD);
@@ -337,31 +337,31 @@ Bool FileIO_AtomicUpdate(FileIODescriptor *newFD,
#if !defined(VMX86_TOOLS) || !defined(__FreeBSD__)
FileIOResult FileIO_Readv(FileIODescriptor *fd,
- struct iovec *v,
+ struct iovec const *v,
int count,
size_t totalSize,
size_t *bytesRead);
FileIOResult FileIO_Writev(FileIODescriptor *fd,
- struct iovec *v,
+ struct iovec const *v,
int count,
size_t totalSize,
size_t *bytesWritten);
#endif
-FileIOResult FileIO_Preadv(FileIODescriptor *fd, // IN: File descriptor
- struct iovec *entries, // IN: Vector to read into
- int numEntries, // IN: Number of vector entries
- uint64 offset, // IN: Offset to start reading
- size_t totalSize, // IN: totalSize (bytes) in entries
- size_t *actual); // OUT: number of bytes read
+FileIOResult FileIO_Preadv(FileIODescriptor *fd, // IN: File descriptor
+ struct iovec const *entries, // IN: Vector to read into
+ int numEntries, // IN: Number of vector entries
+ uint64 offset, // IN: Offset to start reading
+ size_t totalSize, // IN: totalSize (bytes) in entries
+ size_t *actual); // OUT: number of bytes read
-FileIOResult FileIO_Pwritev(FileIODescriptor *fd, // IN: File descriptor
- struct iovec *entries, // IN: Vector to write from
- int numEntries, // IN: Number of vector entries
- uint64 offset, // IN: Offset to start writing
- size_t totalSize, // IN: Total size (bytes) in entries
- size_t *actual); // OUT: number of bytes written
+FileIOResult FileIO_Pwritev(FileIODescriptor *fd, // IN: File descriptor
+ struct iovec const *entries, // IN: Vector to write from
+ int numEntries, // IN: Number of vector entries
+ uint64 offset, // IN: Offset to start writing
+ size_t totalSize, // IN: Total size (bytes) in entries
+ size_t *actual); // OUT: number of bytes written
FileIOResult FileIO_Pread(FileIODescriptor *fd, // IN: File descriptor
void *buf, // IN: Buffer to read into
@@ -373,30 +373,32 @@ FileIOResult FileIO_Pwrite(FileIODescriptor *fd, // IN: File descriptor
size_t len, // IN: Length of the buffer
uint64 offset); // IN: Offset to start writing
-FileIOResult FileIO_Access(ConstUnicode pathName,
+FileIOResult FileIO_Access(const char *pathName,
int accessMode);
Bool FileIO_Truncate(FileIODescriptor *file,
uint64 newSize);
-int FileIO_Sync(const FileIODescriptor *file);
+FileIOResult FileIO_Sync(const FileIODescriptor *file);
FileIOResult FileIO_GetAllocSize(const FileIODescriptor *fd,
uint64 *logicalBytes,
uint64 *allocedBytes);
+
int64 FileIO_GetSize(const FileIODescriptor *fd);
-Bool FileIO_SetAllocSize(const FileIODescriptor *fd, uint64 size);
+Bool FileIO_SetAllocSize(const FileIODescriptor *fd,
+ uint64 size);
-FileIOResult FileIO_GetAllocSizeByPath(ConstUnicode pathName,
+FileIOResult FileIO_GetAllocSizeByPath(const char *pathName,
uint64 *logicalBytes,
uint64 *allocedBytes);
-int64 FileIO_GetSizeByPath(ConstUnicode pathName);
+int64 FileIO_GetSizeByPath(const char *pathName);
-Bool FileIO_Close(FileIODescriptor *file);
+FileIOResult FileIO_Close(FileIODescriptor *file);
-Bool FileIO_CloseAndUnlink(FileIODescriptor *file);
+FileIOResult FileIO_CloseAndUnlink(FileIODescriptor *file);
uint32 FileIO_GetFlags(FileIODescriptor *file);
@@ -415,7 +417,7 @@ FileIOResult FileIO_Unlock(FileIODescriptor *file);
/* Only users not using FileIO_Open should use these two */
void FileIO_Init(FileIODescriptor *fd,
- ConstUnicode pathName);
+ const char *pathName);
void FileIO_Cleanup(FileIODescriptor *fd);
@@ -431,18 +433,18 @@ FileIODescriptor FileIO_CreateFDWin32(HANDLE win32,
FileIODescriptor FileIO_CreateFDPosix(int posix,
int flags);
-int FileIO_PrivilegedPosixOpen(ConstUnicode pathName,
+int FileIO_PrivilegedPosixOpen(const char *pathName,
int flags);
#endif
FILE *FileIO_DescriptorToStream(FileIODescriptor *fd,
Bool textMode);
-ConstUnicode FileIO_Filename(FileIODescriptor *fd);
+const char *FileIO_Filename(FileIODescriptor *fd);
/*
*-------------------------------------------------------------------------
- *
+ *
* FileIO_IsSuccess --
*
* Returns TRUE if the error code is success.
@@ -472,6 +474,11 @@ FileIO_IsSuccess(FileIOResult res) // IN
Bool FileIO_IsSuccess(FileIOResult res);
#endif
-Bool FileIO_SupportsPrealloc(const char *pathName, Bool fsCheck);
+Bool FileIO_SupportsPrealloc(const char *pathName,
+ Bool fsCheck);
+
+#ifdef __cplusplus
+} // extern "C" {
+#endif
#endif // _FILEIO_H_
diff --git a/open-vm-tools/lib/include/fileLock.h b/open-vm-tools/lib/include/fileLock.h
index a9a28aac..a40836ca 100644
--- a/open-vm-tools/lib/include/fileLock.h
+++ b/open-vm-tools/lib/include/fileLock.h
@@ -50,9 +50,9 @@
// File locking functions
typedef struct FileLockToken FileLockToken;
-Unicode FileLock_TokenPathName(const FileLockToken *fileLockToken);
+char *FileLock_TokenPathName(const FileLockToken *fileLockToken);
-FileLockToken *FileLock_Lock(ConstUnicode filePath,
+FileLockToken *FileLock_Lock(const char *filePath,
const Bool readOnly,
const uint32 msecMaxWaitTime,
int *err,
@@ -62,15 +62,15 @@ Bool FileLock_Unlock(const FileLockToken *lockToken,
int *err,
MsgList **msgs);
-Bool FileLock_IsLocked(ConstUnicode filePath,
+Bool FileLock_IsLocked(const char *filePath,
int *err,
MsgList **msgs);
-Bool FileLock_Remove(ConstUnicode filePath,
+Bool FileLock_Remove(const char *filePath,
int *err,
MsgList **msgs);
-Bool FileLock_CleanupVM(ConstUnicode cfgfilePath,
+Bool FileLock_CleanupVM(const char *cfgfilePath,
int *err,
MsgList **msgs);
diff --git a/open-vm-tools/lib/include/file_extensions.h b/open-vm-tools/lib/include/file_extensions.h
index e3164156..4d5e6e99 100644
--- a/open-vm-tools/lib/include/file_extensions.h
+++ b/open-vm-tools/lib/include/file_extensions.h
@@ -74,6 +74,14 @@
#define VRM_HOTFIX_FILE_EXTENSION "vmhf" // ACE hotfix response
/*
+ * VM Download.
+ */
+
+#define RVM_DOWNLOAD_FILE_EXTENSION "vmdownload" // Downloaded file
+#define RVM_STATE_FILE_EXTENSION "vmstate" // Download metadata
+#define DOWNLOAD_BUNDLE_FILE_EXTENSION "vmdownload" // VM download bundle directory
+
+/*
* Other file types.
*/
diff --git a/open-vm-tools/lib/include/ghIntegrationCommon.h b/open-vm-tools/lib/include/ghIntegrationCommon.h
new file mode 100644
index 00000000..d12d0951
--- /dev/null
+++ b/open-vm-tools/lib/include/ghIntegrationCommon.h
@@ -0,0 +1,34 @@
+/*********************************************************
+ * Copyright (C) 2008-2014 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * ghIntegrationCommon.h --
+ *
+ * Common data structures and definitions used by Guest/Host Integration.
+ */
+
+#ifndef _GHINTEGRATIONCOMMON_H_
+#define _GHINTEGRATIONCOMMON_H_
+
+/*
+ * Common data structures and definitions used by Guest/Host Integration.
+ */
+#define GHI_HGFS_SHARE_URL_UTF8 "x-vmware-share://"
+#define GHI_HGFS_SHARE_URL _T(GHI_HGFS_SHARE_URL_UTF8)
+
+#endif // ifndef _GHINTEGRATIONCOMMON_H_
diff --git a/open-vm-tools/lib/include/guestInfo.h b/open-vm-tools/lib/include/guestInfo.h
index 773fff47..2be878f2 100644
--- a/open-vm-tools/lib/include/guestInfo.h
+++ b/open-vm-tools/lib/include/guestInfo.h
@@ -44,7 +44,6 @@
#include "vm_basic_types.h"
#include "dbllnklst.h"
-#include "guestStats.h"
#ifndef N_PLAT_NLM
#include "guestrpc/nicinfo.h"
#endif // #ifndef N_PLAT_NLM
@@ -54,6 +53,7 @@
#define MAX_NICS 16
#define MAX_IPS 8 // Max number of IP addresses for a single NIC
+#define INFO_IPADDRESS_V2_MAX_IPS 64
#define MAC_ADDR_SIZE 19
#define IP_ADDR_SIZE 16
#define PARTITION_NAME_SIZE MAX_VALUE_LEN
@@ -72,6 +72,7 @@ typedef enum {
INFO_UPTIME,
INFO_MEMORY,
INFO_IPADDRESS_V2,
+ INFO_IPADDRESS_V3,
INFO_MAX
} GuestInfoType;
diff --git a/open-vm-tools/lib/include/guestStats.h b/open-vm-tools/lib/include/guestStats.h
index 3cb937a8..2e6a3433 100644
--- a/open-vm-tools/lib/include/guestStats.h
+++ b/open-vm-tools/lib/include/guestStats.h
@@ -30,44 +30,255 @@
#define INCLUDE_ALLOW_VMKERNEL
#include "includeCheck.h"
+#include "vm_assert.h"
#include "vm_basic_types.h"
+/*
+ * Version 1: Legacy data
+ * Version 2: Dead
+ * Version 3: Dead
+ * Version 4: Dead
+ * Version 5: Legacy structure followed by one or more GuestStat
+ * structures and data.
+ */
+
+#define GUESTMEMINFO_V1 1
+#define GUESTMEMINFO_V2 2
+#define GUESTMEMINFO_V3 3
+#define GUESTMEMINFO_V4 4
+#define GUESTMEMINFO_V5 5
+
+/*
+ * Flags for legacy GuestMemInfo
+ *
+ * This is deprecated. All new values are returned via a GuestStat list.
+ */
+
+#define MEMINFO_MEMTOTAL (1 << 0)
+#define MEMINFO_DEPRECATED1 (1 << 1)
+#define MEMINFO_DEPRECATED2 (1 << 2)
+#define MEMINFO_DEPRECATED3 (1 << 3)
+#define MEMINFO_DEPRECATED4 (1 << 4)
+#define MEMINFO_DEPRECATED5 (1 << 5)
+#define MEMINFO_DEPRECATED6 (1 << 6)
+#define MEMINFO_DEPRECATED7 (1 << 7)
+#define MEMINFO_DEPRECATED8 (1 << 8)
+#define MEMINFO_DEPRECATED9 (1 << 9)
+#define MEMINFO_HUGEPAGESTOTAL (1 << 10)
+#define MEMINFO_DEPRECATED10 (1 << 11)
+#define MEMINFO_DEPRECATED11 (1 << 12)
+
+/*
+ * Legacy GuestMemInfo structure.
+ *
+ * It should stay the same to ensure binary compatibility.
+ */
+
typedef
#include "vmware_pack_begin.h"
struct GuestMemInfo {
- uint32 version; ///< MemInfo structure version.
- uint32 flags; ///< Indicates which stats are valid.
- uint64 memTotal; ///< Total physical memory in Kb.
- uint64 memFree; ///< Physical memory available in Kb.
- uint64 memBuff; ///< Physical memory used as buffer cache in Kb.
- uint64 memCache; ///< Physical memory used as cache in Kb.
- uint64 memActive; ///< Physical memory actively in use in Kb (working set)
- uint64 memInactive; ///< Physical memory inactive in Kb (cold pages)
- uint64 swapInRate; ///< Memory swapped out in Kb / sec.
- uint64 swapOutRate; ///< Memory swapped out in Kb / sec.
- uint64 ioInRate; ///< Amount of I/O in Kb / sec.
- uint64 ioOutRate; ///< Amount of I/O out in Kb / sec.
- uint64 hugePagesTotal; ///< Total number of huge pages.
- uint64 hugePagesFree; ///< Available number of huge pages.
- uint64 memPinned; ///< Unreclaimable physical memory in 4K page size.
+ uint32 version; ///< MemInfo structure version.
+ uint32 flags; ///< Indicates which stats are valid.
+ uint64 memTotal; ///< Total physical memory in Kb.
+ uint64 deprecated1[9]; ///< No longer used.
+ uint64 hugePagesTotal; ///< Total number of huge pages.
+ uint64 deprecated2[2]; ///< No longer used.
}
#include "vmware_pack_end.h"
GuestMemInfo;
-/* Flags for GuestMemInfo. */
-#define MEMINFO_MEMTOTAL (1 << 0)
-#define MEMINFO_MEMFREE (1 << 1)
-#define MEMINFO_MEMBUFF (1 << 2)
-#define MEMINFO_MEMCACHE (1 << 3)
-#define MEMINFO_MEMACTIVE (1 << 4)
-#define MEMINFO_MEMINACTIVE (1 << 5)
-#define MEMINFO_SWAPINRATE (1 << 6)
-#define MEMINFO_SWAPOUTRATE (1 << 7)
-#define MEMINFO_IOINRATE (1 << 8)
-#define MEMINFO_IOOUTRATE (1 << 9)
-#define MEMINFO_HUGEPAGESTOTAL (1 << 10)
-#define MEMINFO_HUGEPAGESFREE (1 << 11)
-#define MEMINFO_MEMPINNED (1 << 12)
+/*
+ * A stat begins with a header. The header has a mask which says what data
+ * follows. Each datum has a size field which says how much data follows so it
+ * can be used or ignored. The order of the data that follows is that of the
+ * bits, lowest order bit to highest.
+ */
-#endif // _GUEST_STATS_H_
+typedef enum {
+ GUEST_DATUM_PRAGMA = 0x0001, // escape hatch (future expansion)
+ GUEST_DATUM_NAMESPACE = 0x0002, // UTF8 string
+ GUEST_DATUM_ID = 0x0004, // uint8 - uint64
+ GUEST_DATUM_VALUE_TYPE_ENUM = 0x0008, // uint8 - uint32
+ GUEST_DATUM_VALUE_TYPE_STRING = 0x0010, // UTF8 string
+ GUEST_DATUM_VALUE_UNIT_ENUM = 0x0020, // uint8 - uint32
+ GUEST_DATUM_VALUE_UNIT_STRING = 0x0040, // UTF8 string
+ GUEST_DATUM_VALUE = 0x0080, // value data
+} GuestDatum;
+
+typedef
+#include "vmware_pack_begin.h"
+struct GuestStatHeader {
+ GuestDatum datumFlags; // Indicates how many and which data follow
+}
+#include "vmware_pack_end.h"
+GuestStatHeader;
+
+typedef
+#include "vmware_pack_begin.h"
+struct GuestDatumHeader {
+ uint16 dataSize; // dataSize - May be zero
+ char data[0]; // data - if dataSize is not zero.
+}
+#include "vmware_pack_end.h"
+GuestDatumHeader;
+
+/*
+ * Units datum enum.
+ * Note: The entirety (all bits) of the units must always be understood by a client.
+ *
+ * First we define some modifiers, then the enum itself
+ *
+ * bits 0-5 define base types (information, time, etc.)
+ * bits 6-10 are modifiers, four of which are reserved (in the future, we could
+ * define two of them as custom modifiers, for things like changing the radix from 2^10
+ * to 10^3 for storage, or for denoting rates are in 100ns units).
+ */
+#define GuestUnitsModifier_Rate 0x0040
+#define GuestUnitsModifier_Reserved0 0x0080
+#define GuestUnitsModifier_Reserved1 0x0100
+#define GuestUnitsModifier_Reserved2 0x0200
+#define GuestUnitsModifier_Reserved3 0x0400
+
+/*
+ * bits 11-15 are scale modifiers:
+ * This includes common scales: (P)ositive powers, (N)egative powers,
+ * and (C)ustom scales (bits, pages, etc.), which are always type specific.
+ */
+#define GuestUnitsScale_P0 0x0000
+#define GuestUnitsScale_P1 0x0800
+#define GuestUnitsScale_P2 0x1000
+#define GuestUnitsScale_P3 0x1800
+#define GuestUnitsScale_P4 0x2000
+#define GuestUnitsScale_P5 0x2800
+#define GuestUnitsScale_P6 0x3000
+#define GuestUnitsScale_Reserved0 0x3800
+
+#define GuestUnitsScale_N1 0x4000
+#define GuestUnitsScale_N2 0x4800
+#define GuestUnitsScale_N3 0x5000
+#define GuestUnitsScale_N4 0x5800
+#define GuestUnitsScale_N5 0x6000
+#define GuestUnitsScale_N6 0x6800
+#define GuestUnitsScale_Reserved1 0x7000
+#define GuestUnitsScale_Reserved2 0x7800
+
+#define GuestUnitsScale_C0 0x8000
+#define GuestUnitsScale_C1 0x8800
+#define GuestUnitsScale_C2 0x9000
+#define GuestUnitsScale_C3 0x9800
+// 0xA000-0xF800 are reserved.
+
+typedef enum {
+ GuestUnitsInvalid = 0, // Must never be sent
+ GuestUnitsNone = 1, // A valid value, but not any of the below units.
+ GuestUnitsNumber = 2, // default radix is 1000
+ GuestUnitsInformation = 3, // default radix is 1024
+ GuestUnitsDuration = 4, // default radix is 1000
+ GuestUnitsCycles = 5, // default radix is 1000
+
+ GuestUnitsBytes = GuestUnitsInformation | GuestUnitsScale_P0,
+ GuestUnitsKiB = GuestUnitsInformation | GuestUnitsScale_P1,
+ GuestUnitsMiB = GuestUnitsInformation | GuestUnitsScale_P2,
+ GuestUnitsPages = GuestUnitsInformation | GuestUnitsScale_C0,
+ GuestUnitsHugePages = GuestUnitsInformation | GuestUnitsScale_C1,
+ GuestUnitsBytesPerSecond = GuestUnitsBytes | GuestUnitsModifier_Rate,
+ GuestUnitsKiBPerSecond = GuestUnitsKiB | GuestUnitsModifier_Rate,
+ GuestUnitsMiBPerSecond = GuestUnitsMiB | GuestUnitsModifier_Rate,
+ GuestUnitsPagesPerSecond = GuestUnitsPages | GuestUnitsModifier_Rate,
+ GuestUnitsHugePagesPerSecond = GuestUnitsHugePages | GuestUnitsModifier_Rate,
+
+ GuestUnitsAttoSeconds = GuestUnitsDuration | GuestUnitsScale_N6,
+ GuestUnitsFemtoSeconds = GuestUnitsDuration | GuestUnitsScale_N5,
+ GuestUnitsPicoSeconds = GuestUnitsDuration | GuestUnitsScale_N4,
+ GuestUnitsNanoSeconds = GuestUnitsDuration | GuestUnitsScale_N3,
+ GuestUnitsMicroSeconds = GuestUnitsDuration | GuestUnitsScale_N2,
+ GuestUnitsMilliSeconds = GuestUnitsDuration | GuestUnitsScale_N1,
+ GuestUnitsSeconds = GuestUnitsDuration | GuestUnitsScale_P0,
+
+ GuestUnitsHz = GuestUnitsCycles | GuestUnitsScale_P0 | GuestUnitsModifier_Rate,
+ GuestUnitsKiloHz = GuestUnitsCycles | GuestUnitsScale_P1 | GuestUnitsModifier_Rate,
+ GuestUnitsMegaHz = GuestUnitsCycles | GuestUnitsScale_P2 | GuestUnitsModifier_Rate,
+ GuestUnitsGigaHz = GuestUnitsCycles | GuestUnitsScale_P3 | GuestUnitsModifier_Rate,
+ GuestUnitsTeraHz = GuestUnitsCycles | GuestUnitsScale_P4 | GuestUnitsModifier_Rate,
+
+ GuestUnitsPercent = GuestUnitsNumber | GuestUnitsScale_C0, // integers: must be 0...100; FP: 0.0...1.0
+ GuestUnitsNumberPerSecond = GuestUnitsNumber | GuestUnitsModifier_Rate,
+} GuestValueUnits;
+
+/*
+ * Data type datum enum.
+ * Note: The entirety (all bits) of the type must always be understood by a client.
+ *
+ * Bits 0-5 are for types.
+ * Bits 6-15 are reserved. In the future, one bit will denote arrays.
+ */
+#define GuestTypeModifier_Reserved0 0x0040 // More Reserved1-9 not shown.
+
+typedef enum {
+ GuestTypeInvalid, // Must never be sent
+ GuestTypeNil, // A stat that has no value
+ GuestTypeInt8, // Little endian
+ GuestTypeUint8, // Little endian
+ GuestTypeInt16, // Little endian
+ GuestTypeUint16, // Little endian
+ GuestTypeInt32, // Little endian
+ GuestTypeUint32, // Little endian
+ GuestTypeInt64, // Little endian
+ GuestTypeUint64, // Little endian
+ GuestTypeFloat, // IEEE 754
+ GuestTypeDouble, // IEEE 754
+ GuestTypeString, // NUL terminated UTF8
+ GuestTypeBinary, // Binary blob
+} GuestValueType;
+
+/*
+ * Defines the namespace used for guest tools buildin query.
+ */
+#define GUEST_TOOLS_NAMESPACE "_tools/v1"
+
+/*
+ * Defined stat IDs for guest tools builtin query.
+ * See vmx/vigorapi/GuestStats.java for documentation
+ *
+ * NOTE: These IDs are relative to GUEST_TOOLS_NAMESPACE
+ * NOTE: DO NOT re-order or remove the IDs. IDs can only be added to the end,
+ * unless you make the totally backward-compatibility breaking change
+ * of bumping the namespace version.
+ */
+#define GUEST_STAT_TOOLS_IDS \
+ DEFINE_GUEST_STAT(GuestStatID_Invalid, 0, "__INVALID__") \
+ DEFINE_GUEST_STAT(GuestStatID_None, 1, "__NONE__") \
+ DEFINE_GUEST_STAT(GuestStatID_ContextSwapRate, 2, "guest.contextSwapRate") \
+ DEFINE_GUEST_STAT(GuestStatID_MemActiveFileCache, 3, "guest.mem.activeFileCache") \
+ DEFINE_GUEST_STAT(GuestStatID_MemFree, 4, "guest.mem.free") \
+ DEFINE_GUEST_STAT(GuestStatID_MemNeeded, 5, "guest.mem.needed") \
+ DEFINE_GUEST_STAT(GuestStatID_MemPhysUsable, 6, "guest.mem.physUsable") \
+ DEFINE_GUEST_STAT(GuestStatID_PageInRate, 7, "guest.page.inRate") \
+ DEFINE_GUEST_STAT(GuestStatID_PageOutRate, 8, "guest.page.outRate") \
+ DEFINE_GUEST_STAT(GuestStatID_SwapSpaceRemaining, 9, "guest.swap.spaceRemaining") \
+ DEFINE_GUEST_STAT(GuestStatID_PhysicalPageSize, 10, "guest.page.size") \
+ DEFINE_GUEST_STAT(GuestStatID_HugePageSize, 11, "guest.hugePage.size") \
+ DEFINE_GUEST_STAT(GuestStatID_Linux_HugePagesTotal, 12, "guest.hugePage.total") \
+ DEFINE_GUEST_STAT(GuestStatID_Max, 13, "__MAX__")
+
+/*
+ * Define stats enumeration
+ */
+#undef DEFINE_GUEST_STAT
+#define DEFINE_GUEST_STAT(x,y,z) x,
+typedef enum GuestStatToolsID {
+ GUEST_STAT_TOOLS_IDS
+} GuestStatToolsID;
+
+/*
+ * Enforce ordering and compactness of the enumeration
+ */
+#undef DEFINE_GUEST_STAT
+#define DEFINE_GUEST_STAT(x,y,z) ASSERT_ON_COMPILE(x==y);
+
+MY_ASSERTS(GUEST_STAT_IDS_ARE_WELL_ORDERED, GUEST_STAT_TOOLS_IDS)
+
+#undef DEFINE_GUEST_STAT
+
+#endif // _GUEST_STATS_H_
diff --git a/open-vm-tools/lib/include/guest_os.h b/open-vm-tools/lib/include/guest_os.h
index 4fc9ea7b..d5d190a8 100644
--- a/open-vm-tools/lib/include/guest_os.h
+++ b/open-vm-tools/lib/include/guest_os.h
@@ -116,7 +116,9 @@ Bool Gos_InSetArray(uint32 gos, const uint32 *set);
#define ALLWINTENCLIENT64 BS(WINTEN_64)
#define ALLWINTENCLIENT ALLWINTENCLIENT32, ALLWINTENCLIENT64
-#define ALLWINTEN ALLWINTENSERVER, ALLWINTENCLIENT
+#define ALLWINTEN32 ALLWINTENCLIENT32
+#define ALLWINTEN64 ALLWINTENCLIENT64, ALLWINTENSERVER
+#define ALLWINTEN ALLWINTENCLIENT, ALLWINTENSERVER
#define ALLHYPER_V BS(HYPER_V)
@@ -144,6 +146,10 @@ Bool Gos_InSetArray(uint32 gos, const uint32 *set);
#define ALLWIN64 ALLWINNT64
#define ALLWIN ALLWIN32, ALLWIN64
+#define ALLOTHER BS(OTHER), BS(OTHER_64)
+
+#define ALLPHOTON BS(PHOTON_64)
+
#define ALLSOLARIS BS(SOLARIS_6_AND_7), BS(SOLARIS8), \
BS(SOLARIS9), BS(SOLARIS10), \
BS(SOLARIS10_64)
@@ -154,9 +160,9 @@ Bool Gos_InSetArray(uint32 gos, const uint32 *set);
#define ALL26XLINUX64 BS(OTHER26XLINUX_64), BS(DEBIAN45_64), \
BS(RHEL_64)
#define ALL3XLINUX32 BS(OTHER3XLINUX)
-#define ALL3XLINUX64 BS(OTHER3XLINUX_64)
+#define ALL3XLINUX64 BS(OTHER3XLINUX_64), BS(PHOTON_64)
-#define ALLVMKERNEL BS(VMKERNEL), BS(VMKERNEL5)
+#define ALLVMKERNEL BS(VMKERNEL), BS(VMKERNEL5), BS(VMKERNEL6)
#define ALLLINUX32 BS(OTHER24XLINUX), ALL26XLINUX32, ALL3XLINUX32, \
BS(OTHERLINUX), BS(VMKERNEL)
@@ -183,6 +189,7 @@ Bool Gos_InSetArray(uint32 gos, const uint32 *set);
/* vmkernel (ESX) */
#define STR_OS_ESX_4 "VMware ESX 4"
#define STR_OS_ESX_5 "VMware ESX 5"
+#define STR_OS_ESX_6 "VMware ESX 6"
/* Linux */
#define STR_OS_ANNVIX "Annvix"
@@ -226,6 +233,8 @@ Bool Gos_InSetArray(uint32 gos, const uint32 *set);
#define STR_OS_OTHER_3X "other3xlinux"
#define STR_OS_OTHER_3X_FULL "Other Linux 3.x kernel"
#define STR_OS_OTHER_FULL "Other Linux"
+#define STR_OS_PHOTON "vmware-photon"
+#define STR_OS_PHOTON_FULL "VMware Photon"
#define STR_OS_PLD "PLD"
#define STR_OS_RED_HAT "redhat"
#define STR_OS_RED_HAT_EN "rhel"
@@ -442,13 +451,13 @@ Bool Gos_InSetArray(uint32 gos, const uint32 *set);
#define STR_OS_WIN_TEN_GENERIC_FULL "Windows 10"
-/* Windows Server Threshold */
+/* Windows Server 2016 */
#define STR_OS_WIN_TENSERVER_X64 "windows9srv-64"
/* THIS SPACE FOR RENT (Windows 10 official server variant names) */
-#define STR_OS_WIN_TENSERVER_GENERIC_FULL "Windows Server Threshold"
+#define STR_OS_WIN_TENSERVER_GENERIC_FULL "Windows Server 2016"
/* Microsoft Hyper-V */
#define STR_OS_HYPER_V "winHyperV"
diff --git a/open-vm-tools/lib/include/guest_os_tables.h b/open-vm-tools/lib/include/guest_os_tables.h
index e4afd141..9449035d 100644
--- a/open-vm-tools/lib/include/guest_os_tables.h
+++ b/open-vm-tools/lib/include/guest_os_tables.h
@@ -24,75 +24,77 @@
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
-#define GUEST_OS_TYPE_GEN \
- GOT(GUEST_OS_ANY) \
- GOT(GUEST_OS_DOS) \
- GOT(GUEST_OS_WIN31) \
- GOT(GUEST_OS_WIN95) \
- GOT(GUEST_OS_WIN98) \
- GOT(GUEST_OS_WINME) \
- GOT(GUEST_OS_WINNT) \
- GOT(GUEST_OS_WIN2000) \
- GOT(GUEST_OS_WINXP) \
- GOT(GUEST_OS_WINXPPRO_64) \
- GOT(GUEST_OS_WINNET) \
- GOT(GUEST_OS_WINNET_64) \
- GOT(GUEST_OS_LONGHORN) \
- GOT(GUEST_OS_LONGHORN_64) \
- GOT(GUEST_OS_WINVISTA) \
- GOT(GUEST_OS_WINVISTA_64) \
- GOT(GUEST_OS_WINSEVEN) /* Windows 7 */ \
- GOT(GUEST_OS_WINSEVEN_64) /* Windows 7 */ \
- GOT(GUEST_OS_WIN2008R2_64) /* Server 2008 R2 */ \
- GOT(GUEST_OS_WINEIGHT) /* Windows 8 */ \
- GOT(GUEST_OS_WINEIGHT_64) /* Windows 8 x64 */ \
- GOT(GUEST_OS_WINEIGHTSERVER_64) /* Windows 8 Server X64 */ \
- GOT(GUEST_OS_WINTEN) /* Windows 10 */ \
- GOT(GUEST_OS_WINTEN_64) /* Windows 10 x64 */ \
- GOT(GUEST_OS_WINTENSERVER_64) /* Windows 10 Server X64 */\
- GOT(GUEST_OS_HYPER_V) /* Microsoft Hyper-V */ \
- GOT(GUEST_OS_OS2) \
- GOT(GUEST_OS_ECOMSTATION) /* OS/2 variant; 1.x */ \
- GOT(GUEST_OS_ECOMSTATION2) /* OS/2 variant; 2.x */ \
- GOT(GUEST_OS_OTHER24XLINUX) \
- GOT(GUEST_OS_OTHER24XLINUX_64) \
- GOT(GUEST_OS_OTHER26XLINUX) \
- GOT(GUEST_OS_OTHER26XLINUX_64) \
- GOT(GUEST_OS_OTHER3XLINUX) \
- GOT(GUEST_OS_OTHER3XLINUX_64) \
- GOT(GUEST_OS_OTHERLINUX) \
- GOT(GUEST_OS_OTHERLINUX_64) \
- GOT(GUEST_OS_OTHER) \
- GOT(GUEST_OS_OTHER_64) \
- GOT(GUEST_OS_UBUNTU) \
- GOT(GUEST_OS_DEBIAN45) \
- GOT(GUEST_OS_DEBIAN45_64) \
- GOT(GUEST_OS_RHEL) \
- GOT(GUEST_OS_RHEL_64) \
- GOT(GUEST_OS_FREEBSD) \
- GOT(GUEST_OS_FREEBSD_64) \
- GOT(GUEST_OS_SOLARIS_6_AND_7) \
- GOT(GUEST_OS_SOLARIS8) \
- GOT(GUEST_OS_SOLARIS9) \
- GOT(GUEST_OS_SOLARIS10) \
- GOT(GUEST_OS_SOLARIS10_64) \
- GOT(GUEST_OS_SOLARIS11_64) \
- GOT(GUEST_OS_DARWIN9) /* Mac OS 10.5 */ \
- GOT(GUEST_OS_DARWIN9_64) \
- GOT(GUEST_OS_DARWIN10) /* Mac OS 10.6 */ \
- GOT(GUEST_OS_DARWIN10_64) \
- GOT(GUEST_OS_DARWIN11) /* Mac OS 10.7 */ \
- GOT(GUEST_OS_DARWIN11_64) \
- GOT(GUEST_OS_DARWIN12_64) /* Mac OS 10.8 */ \
- GOT(GUEST_OS_DARWIN13_64) /* Mac OS 10.9 */ \
- GOT(GUEST_OS_DARWIN14_64) /* Mac OS 10.10 */ \
- GOT(GUEST_OS_OPENSERVER_5_AND_6) \
- GOT(GUEST_OS_UNIXWARE7) \
- GOT(GUEST_OS_NETWARE4) \
- GOT(GUEST_OS_NETWARE5) \
- GOT(GUEST_OS_NETWARE6) \
- GOT(GUEST_OS_VMKERNEL) /* ESX 4.x */ \
- GOT(GUEST_OS_VMKERNEL5) /* ESX 5.x and later */ \
+#define GUEST_OS_TYPE_GEN \
+ GOT(GUEST_OS_ANY) \
+ GOT(GUEST_OS_DOS) \
+ GOT(GUEST_OS_WIN31) \
+ GOT(GUEST_OS_WIN95) \
+ GOT(GUEST_OS_WIN98) \
+ GOT(GUEST_OS_WINME) \
+ GOT(GUEST_OS_WINNT) \
+ GOT(GUEST_OS_WIN2000) \
+ GOT(GUEST_OS_WINXP) \
+ GOT(GUEST_OS_WINXPPRO_64) \
+ GOT(GUEST_OS_WINNET) \
+ GOT(GUEST_OS_WINNET_64) \
+ GOT(GUEST_OS_LONGHORN) \
+ GOT(GUEST_OS_LONGHORN_64) \
+ GOT(GUEST_OS_WINVISTA) \
+ GOT(GUEST_OS_WINVISTA_64) \
+ GOT(GUEST_OS_WINSEVEN) /* Windows 7 */ \
+ GOT(GUEST_OS_WINSEVEN_64) /* Windows 7 */ \
+ GOT(GUEST_OS_WIN2008R2_64) /* Server 2008 R2 */ \
+ GOT(GUEST_OS_WINEIGHT) /* Windows 8 */ \
+ GOT(GUEST_OS_WINEIGHT_64) /* Windows 8 x64 */ \
+ GOT(GUEST_OS_WINEIGHTSERVER_64) /* Windows 8 Server X64 */ \
+ GOT(GUEST_OS_WINTEN) /* Windows 10 */ \
+ GOT(GUEST_OS_WINTEN_64) /* Windows 10 x64 */ \
+ GOT(GUEST_OS_WINTENSERVER_64) /* Windows 10 Server X64 */ \
+ GOT(GUEST_OS_HYPER_V) /* Microsoft Hyper-V */ \
+ GOT(GUEST_OS_OS2) \
+ GOT(GUEST_OS_ECOMSTATION) /* OS/2 variant; 1.x */ \
+ GOT(GUEST_OS_ECOMSTATION2) /* OS/2 variant; 2.x */ \
+ GOT(GUEST_OS_OTHER24XLINUX) \
+ GOT(GUEST_OS_OTHER24XLINUX_64) \
+ GOT(GUEST_OS_OTHER26XLINUX) \
+ GOT(GUEST_OS_OTHER26XLINUX_64) \
+ GOT(GUEST_OS_OTHER3XLINUX) \
+ GOT(GUEST_OS_OTHER3XLINUX_64) \
+ GOT(GUEST_OS_OTHERLINUX) \
+ GOT(GUEST_OS_OTHERLINUX_64) \
+ GOT(GUEST_OS_OTHER) \
+ GOT(GUEST_OS_OTHER_64) \
+ GOT(GUEST_OS_UBUNTU) \
+ GOT(GUEST_OS_DEBIAN45) \
+ GOT(GUEST_OS_DEBIAN45_64) \
+ GOT(GUEST_OS_RHEL) \
+ GOT(GUEST_OS_RHEL_64) \
+ GOT(GUEST_OS_FREEBSD) \
+ GOT(GUEST_OS_FREEBSD_64) \
+ GOT(GUEST_OS_SOLARIS_6_AND_7) \
+ GOT(GUEST_OS_SOLARIS8) \
+ GOT(GUEST_OS_SOLARIS9) \
+ GOT(GUEST_OS_SOLARIS10) \
+ GOT(GUEST_OS_SOLARIS10_64) \
+ GOT(GUEST_OS_SOLARIS11_64) \
+ GOT(GUEST_OS_DARWIN9) /* Mac OS 10.5 */ \
+ GOT(GUEST_OS_DARWIN9_64) \
+ GOT(GUEST_OS_DARWIN10) /* Mac OS 10.6 */ \
+ GOT(GUEST_OS_DARWIN10_64) \
+ GOT(GUEST_OS_DARWIN11) /* Mac OS 10.7 */ \
+ GOT(GUEST_OS_DARWIN11_64) \
+ GOT(GUEST_OS_DARWIN12_64) /* Mac OS 10.8 */ \
+ GOT(GUEST_OS_DARWIN13_64) /* Mac OS 10.9 */ \
+ GOT(GUEST_OS_DARWIN14_64) /* Mac OS 10.10 */ \
+ GOT(GUEST_OS_OPENSERVER_5_AND_6) \
+ GOT(GUEST_OS_UNIXWARE7) \
+ GOT(GUEST_OS_NETWARE4) \
+ GOT(GUEST_OS_NETWARE5) \
+ GOT(GUEST_OS_NETWARE6) \
+ GOT(GUEST_OS_VMKERNEL) /* ESX 4.x */ \
+ GOT(GUEST_OS_VMKERNEL5) /* ESX 5.x */ \
+ GOT(GUEST_OS_VMKERNEL6) /* ESX 6.x and later */ \
+ GOT(GUEST_OS_PHOTON_64) /* VMware Photon IA 64-bit */ \
/* This list must be sorted alphabetically (non-case-sensitive) by gos name. */
@@ -200,7 +202,8 @@
GOSL("unixware7", GUEST_OS_UNIXWARE7) \
GOSL("vmkernel", GUEST_OS_VMKERNEL) \
GOSL("vmkernel5", GUEST_OS_VMKERNEL5) \
- GOSL("vmkernel6", GUEST_OS_VMKERNEL5) \
+ GOSL("vmkernel6", GUEST_OS_VMKERNEL6) \
+ GOSL(STR_OS_PHOTON "-64", GUEST_OS_PHOTON_64) \
GOSL("whistler", GUEST_OS_WINXP) /* old */ \
GOSL("win2000", GUEST_OS_WIN2000) /* old */ \
GOSL(STR_OS_WIN_2000_ADV_SERV, GUEST_OS_WIN2000) \
diff --git a/open-vm-tools/lib/include/hashTable.h b/open-vm-tools/lib/include/hashTable.h
index e80834db..c422931b 100644
--- a/open-vm-tools/lib/include/hashTable.h
+++ b/open-vm-tools/lib/include/hashTable.h
@@ -58,77 +58,77 @@ typedef int (*HashTableForEachCallback)(const char *key,
#define HASH_FLAG_COPYKEY 0x10 // copy string key
HashTable *
-HashTable_Alloc(uint32 numEntries,
- int keyType,
- HashTableFreeEntryFn fn);
+HashTable_Alloc(uint32 numEntries, // IN:
+ int keyType, // IN:
+ HashTableFreeEntryFn fn); // IN/OPT:
HashTable *
-HashTable_AllocOnce(Atomic_Ptr *var,
- uint32 numEntries,
- int keyType,
- HashTableFreeEntryFn fn);
+HashTable_AllocOnce(Atomic_Ptr *var, // IN/OUT:
+ uint32 numEntries, // IN:
+ int keyType, // IN:
+ HashTableFreeEntryFn fn); // IN/OPT:
void
-HashTable_Free(HashTable *hashTable);
+HashTable_Free(HashTable *hashTable); // IN/OUT:
void
-HashTable_FreeUnsafe(HashTable *hashTable);
+HashTable_FreeUnsafe(HashTable *hashTable); // IN/OUT:
Bool
-HashTable_Insert(HashTable *hashTable,
- const void *keyStr,
- void *clientData);
+HashTable_Insert(HashTable *hashTable, // IN/OUT:
+ const void *keyStr, // IN:
+ void *clientData); // IN/OPT:
Bool
-HashTable_Lookup(HashTable *hashTable,
- const void *keyStr,
- void **clientData);
+HashTable_Lookup(HashTable *hashTable, // IN:
+ const void *keyStr, // IN:
+ void **clientData); // OUT/OPT:
void *
-HashTable_LookupOrInsert(HashTable *hashTable,
- const void *keyStr,
- void *clientData);
+HashTable_LookupOrInsert(HashTable *hashTable, // IN/OUT:
+ const void *keyStr, // IN:
+ void *clientData); // IN/OPT:
Bool
-HashTable_ReplaceOrInsert(HashTable *hashTable,
- const void *keyStr,
- void *clientData);
+HashTable_ReplaceOrInsert(HashTable *hashTable, // IN/OUT:
+ const void *keyStr, // IN:
+ void *clientData); // IN/OPT
Bool
-HashTable_ReplaceIfEqual(HashTable *hashTable,
- const void *keyStr,
- void *oldClientData,
- void *newClientData);
+HashTable_ReplaceIfEqual(HashTable *hashTable, // IN/OUT:
+ const void *keyStr, // IN:
+ void *oldClientData, // IN/OPT
+ void *newClientData); // IN/OPT
Bool
-HashTable_Delete(HashTable *hashTable,
- const void *keyStr);
+HashTable_Delete(HashTable *hashTable, // IN/OUT:
+ const void *keyStr); // IN:
Bool
-HashTable_LookupAndDelete(HashTable *hashTable,
- const void *keyStr,
- void **clientData);
+HashTable_LookupAndDelete(HashTable *hashTable, // IN/OUT:
+ const void *keyStr, // IN:
+ void **clientData); // OUT:
void
-HashTable_Clear(HashTable *ht);
+HashTable_Clear(HashTable *ht); // IN/OUT:
void
-HashTable_ToArray(const HashTable *ht,
- void ***clientDatas,
- size_t *size);
+HashTable_ToArray(const HashTable *ht, // IN:
+ void ***clientDatas, // OUT:
+ size_t *size); // OUT:
void
-HashTable_KeyArray(const HashTable *ht,
- const void ***keys,
- size_t *size);
+HashTable_KeyArray(const HashTable *ht, // IN:
+ const void ***keys, // OUT:
+ size_t *size); // OUT:
size_t
-HashTable_GetNumElements(const HashTable *ht);
+HashTable_GetNumElements(const HashTable *ht); // IN:
int
-HashTable_ForEach(const HashTable *ht,
- HashTableForEachCallback cb,
- void *clientData);
+HashTable_ForEach(const HashTable *ht, // IN:
+ HashTableForEachCallback cb, // IN:
+ void *clientData); // IN:
/*
* Specialize hash table that uses the callers data structure as its
diff --git a/open-vm-tools/lib/include/hgfsDevLinux.h b/open-vm-tools/lib/include/hgfsDevLinux.h
index 3c66e4a1..04ce3618 100644
--- a/open-vm-tools/lib/include/hgfsDevLinux.h
+++ b/open-vm-tools/lib/include/hgfsDevLinux.h
@@ -32,7 +32,7 @@
/*
* hgfsDev.h --
- *
+ *
* Header for code shared between the hgfs linux kernel module driver
* and the pserver.
*/
@@ -44,12 +44,21 @@
#include "hgfs.h"
#define HGFS_NAME "vmhgfs" // Name of FS (e.g. "mount -t vmhgfs")
+#define HGFS_FUSENAME "vmhgfs-fuse" // Name of FS (e.g. "-o subtype=vmhgfs-fuse")
+#define HGFS_FUSETYPE "fuse." HGFS_FUSENAME // Type of FS (e.g. "fuse.vmhgfs-fuse")
+#define HGFS_MOUNT_POINT "/mnt/hgfs" // Type of FS (e.g. vmhgfs-fuse )
#define HGFS_DEVICE_NAME "dev" // Name of our device under /proc/fs/HGFS_NAME/
#define HGFS_SUPER_MAGIC 0xbacbacbc // Superblock magic number
#define HGFS_PROTOCOL_VERSION 1 // Incremented when something changes
#define HGFS_DEFAULT_TTL 1 // Default TTL for dentries
-/*
+/*
+ * The mount info flags.
+ * These specify flags from options parsed on the mount command line.
+ */
+#define HGFS_MNTINFO_SERVER_INO (1 << 0) /* Use server inode numbers? */
+
+/*
* Mount information, passed from pserver process to kernel
* at mount time.
*
@@ -57,10 +66,13 @@
* loses its pserver, the struct will be used by /sbin/mount.vmhgfs solely.
* As is, it is also used by the Solaris pserver.
*/
-typedef struct HgfsMountInfo {
+typedef
+struct HgfsMountInfo {
uint32 magicNumber; // hgfs magic number
+ uint32 infoSize; // HgfsMountInfo object size
uint32 version; // protocol version
uint32 fd; // file descriptor of client file
+ uint32 flags; // hgfs specific mount flags
#ifndef sun
uid_t uid; // desired owner of files
Bool uidSet; // is the owner actually set?
@@ -77,6 +89,12 @@ typedef struct HgfsMountInfo {
const char *shareNameDir; // desired share name for mounting
#endif
#endif
-} HgfsMountInfo;
+}
+#if __GNUC__
+__attribute__((__packed__))
+#else
+# error Compiler packing...
+#endif
+HgfsMountInfo;
#endif //ifndef _HGFS_DEV_H_
diff --git a/open-vm-tools/lib/include/hgfsEscape.h b/open-vm-tools/lib/include/hgfsEscape.h
index a6754ec0..b24570d9 100644
--- a/open-vm-tools/lib/include/hgfsEscape.h
+++ b/open-vm-tools/lib/include/hgfsEscape.h
@@ -41,14 +41,14 @@
#ifndef __HGFS_ESCAPE_H__
#define __HGFS_ESCAPE_H__
-int HgfsEscape_GetSize(char const *bufIn, // IN
- uint32 sizeIn); // IN
-int HgfsEscape_Do(char const *bufIn, // IN
- uint32 sizeIn, // IN
- uint32 sizeBufOut, // IN
- char *bufOut); // OUT
+int HgfsEscape_GetSize(char const *bufIn,
+ uint32 sizeIn);
+int HgfsEscape_Do(char const *bufIn,
+ uint32 sizeIn,
+ uint32 sizeBufOut,
+ char *bufOut);
-int HgfsEscape_Undo(char *bufIn, // IN
- uint32 sizeIn); // IN
+uint32 HgfsEscape_Undo(char *bufIn,
+ uint32 sizeIn);
#endif // __HGFS_ESCAPE_H__
diff --git a/open-vm-tools/lib/include/hgfsHelper.h b/open-vm-tools/lib/include/hgfsHelper.h
index 40b05fdd..fa1cd850 100644
--- a/open-vm-tools/lib/include/hgfsHelper.h
+++ b/open-vm-tools/lib/include/hgfsHelper.h
@@ -29,10 +29,10 @@
#include "vm_basic_types.h"
#include "unicode.h"
-Bool HgfsHlpr_QuerySharesDefaultRootPath(Unicode *hgfsRootPath);
-void HgfsHlpr_FreeSharesRootPath(Unicode hgfsRootPath);
+Bool HgfsHlpr_QuerySharesDefaultRootPath(char **hgfsRootPath);
+void HgfsHlpr_FreeSharesRootPath(char *hgfsRootPath);
#if defined(_WIN32)
-Bool HgfsHlpr_ReadRegistryDefaultRootPath(Unicode *hgfsRootPath);
+Bool HgfsHlpr_ReadRegistryDefaultRootPath(char **hgfsRootPath);
#endif // _WIN32
#endif
diff --git a/open-vm-tools/lib/include/hgfsProto.h b/open-vm-tools/lib/include/hgfsProto.h
index 758a38ac..58d318ca 100644
--- a/open-vm-tools/lib/include/hgfsProto.h
+++ b/open-vm-tools/lib/include/hgfsProto.h
@@ -137,8 +137,8 @@ typedef enum {
HGFS_OP_DELETE_V4, /* Delete a file or a directory */
HGFS_OP_LINKMOVE_V4, /* Rename/move/create hard link. */
HGFS_OP_FSCTL_V4, /* Sending FS control requests. */
- HGFS_OP_ACCESS_CHECK_V4, /* Flush all cached data to the disk. */
- HGFS_OP_FSYNC_V4, /* Access check. */
+ HGFS_OP_ACCESS_CHECK_V4, /* Access check. */
+ HGFS_OP_FSYNC_V4, /* Flush all cached data to the disk. */
HGFS_OP_QUERY_VOLUME_INFO_V4, /* Query volume information. */
HGFS_OP_OPLOCK_ACQUIRE_V4, /* Acquire OPLOCK. */
HGFS_OP_OPLOCK_BREAK_V4, /* Break or downgrade OPLOCK. */
@@ -787,12 +787,25 @@ HgfsReplyOpenV2;
/* Version 3 of HgfsReplyOpen */
+
+/*
+ * The HGFS open V3 can acquire locks and reserve disk space when requested.
+ * However, current versions of the server don't implement the locking or allocation of
+ * disk space on a create. These results flags indicate to the client if the server
+ * implements handling those fields and so the clients can respond accordingly.
+ */
+typedef uint32 HgfsReplyOpenFlags;
+
+#define HGFS_OPEN_REPLY_ALLOC_DISK_SPACE (1 << 0)
+#define HGFS_OPEN_REPLY_LOCKED_FILE (1 << 1)
+
typedef
#include "vmware_pack_begin.h"
struct HgfsReplyOpenV3 {
HgfsHandle file; /* Opaque file ID used by the server */
HgfsLockType acquiredLock; /* The type of lock acquired by the server */
- uint64 reserved; /* Reserved for future use */
+ HgfsReplyOpenFlags flags; /* Opened file flags */
+ uint32 reserved; /* Reserved for future use */
}
#include "vmware_pack_end.h"
HgfsReplyOpenV3;
diff --git a/open-vm-tools/lib/include/hgfsServer.h b/open-vm-tools/lib/include/hgfsServer.h
index 07da3da6..dfc71bdc 100644
--- a/open-vm-tools/lib/include/hgfsServer.h
+++ b/open-vm-tools/lib/include/hgfsServer.h
@@ -22,19 +22,6 @@
#include "hgfs.h" /* for HGFS_PACKET_MAX */
#include "dbllnklst.h"
-/*
- * Function used for sending updates of server state to the manager.
- * Passed by the caller at session connect time.
- */
-typedef void
-HgfsServerStateLoggerFunc(void *data, // IN
- uint64 cookie); // IN
-
-typedef struct HgfsServerStateLogger {
- HgfsServerStateLoggerFunc *logger; // logger callback
- void *loggerData; // logger callback private data
-} HgfsServerStateLogger;
-
typedef struct HgfsVmxIov {
void *va; /* Virtual addr */
uint64 pa; /* Physical address passed by the guest */
@@ -135,6 +122,50 @@ typedef struct HgfsServerConfig {
uint32 maxCachedOpenNodes;
}HgfsServerConfig;
+/*
+ * Function used to notify HGFS server that a shared folder has been created or updated.
+ * It allows HGFS server to maintain up-to-date list of shared folders and its
+ * properties.
+ */
+typedef uint32 HgfsSharedFolderHandle;
+#define HGFS_INVALID_FOLDER_HANDLE ((HgfsSharedFolderHandle)~((HgfsSharedFolderHandle)0))
+
+typedef HgfsSharedFolderHandle (*HgfsRegisterSharedFolderFunc)(const char *shareName,
+ const char *sharePath,
+ Bool addFolder);
+/*
+ * Callback functions to enumerate the share resources.
+ * Filled in by the HGFS server policy and passed in to the HGFS server
+ * so that it can call out to them to enumerate the shares.
+ */
+typedef void * (*HgfsServerResEnumInitFunc)(void);
+typedef Bool (*HgfsServerResEnumGetFunc)(void *data,
+ char const **name,
+ size_t *len,
+ Bool *done);
+typedef Bool (*HgfsServerResEnumExitFunc)(void *);
+
+typedef struct HgfsServerResEnumCallbacks {
+ HgfsServerResEnumInitFunc init;
+ HgfsServerResEnumGetFunc get;
+ HgfsServerResEnumExitFunc exit;
+} HgfsServerResEnumCallbacks;
+
+
+/*
+ * Server Manager callback functions to enumerate the share resources and state logging.
+ * Passed to the HGFS server on initialization.
+ */
+typedef struct HgfsServerMgrCallbacks {
+ HgfsServerResEnumCallbacks enumResources;
+} HgfsServerMgrCallbacks;
+
+/*
+ * Function used for invalidating nodes and searches that fall outside of a
+ * share when the list of shares changes.
+ */
+typedef void (*HgfsInvalidateObjectsFunc)(DblLnkLst_Links *shares);
+
typedef Bool (*HgfsChannelSendFunc)(void *opaqueSession,
HgfsPacket *packet,
HgfsSendFlags flags);
@@ -158,58 +189,20 @@ typedef struct HgfsServerSessionCallbacks {
void (*sendComplete)(HgfsPacket *, void *);
} HgfsServerSessionCallbacks;
-Bool HgfsServer_InitState(HgfsServerSessionCallbacks **,
+typedef struct HgfsServerCallbacks {
+ HgfsServerSessionCallbacks session;
+ HgfsRegisterSharedFolderFunc registerShare;
+} HgfsServerCallbacks;
+
+Bool HgfsServer_InitState(HgfsServerCallbacks **,
HgfsServerConfig *,
- HgfsServerStateLogger *);
+ HgfsServerMgrCallbacks *);
void HgfsServer_ExitState(void);
uint32 HgfsServer_GetHandleCounter(void);
void HgfsServer_SetHandleCounter(uint32 newHandleCounter);
-/*
- * Function pointers used for getting names in HgfsServerGetDents
- *
- * Functions of this type are expected to return a NUL terminated
- * string and the length of that string.
- */
-typedef Bool
-HgfsGetNameFunc(void *data, // IN
- char const **name, // OUT
- size_t *len, // OUT
- Bool *done); // OUT
-
-/*
- * Associated setup and cleanup function types, which should be called
- * before and after (respectively) HgfsGetNameFunc.
- */
-typedef void *
-HgfsInitFunc(void);
-
-typedef Bool
-HgfsCleanupFunc(void *); // IN
-
-/*
- * Function used for invalidating nodes and searches that fall outside of a
- * share when the list of shares changes.
- */
-typedef void
-HgfsInvalidateObjectsFunc(DblLnkLst_Links *shares); // IN
-
-/*
- * Function used to notify HGFS server that a shared folder has been created or updated.
- * It allows HGFS server to maintain up-to-date list of shared folders and its
- * properties.
- */
-typedef uint32 HgfsSharedFolderHandle;
-#define HGFS_INVALID_FOLDER_HANDLE ((HgfsSharedFolderHandle)~((HgfsSharedFolderHandle)0))
-typedef HgfsSharedFolderHandle
-HgfsRegisterSharedFolderFunc(const char *shareName,
- const char *sharePath,
- Bool addFolder);
-HgfsSharedFolderHandle HgfsServer_RegisterSharedFolder(const char *shareName,
- const char *sharePath,
- Bool addFolder);
void HgfsServer_Quiesce(Bool freeze);
#endif // _HGFS_SERVER_H_
diff --git a/open-vm-tools/lib/include/hgfsServerPolicy.h b/open-vm-tools/lib/include/hgfsServerPolicy.h
index 9919226e..bdb399eb 100644
--- a/open-vm-tools/lib/include/hgfsServerPolicy.h
+++ b/open-vm-tools/lib/include/hgfsServerPolicy.h
@@ -31,12 +31,6 @@
*/
#define HGFS_SERVER_POLICY_ROOT_SHARE_NAME "root"
-Bool
-HgfsServerPolicy_Init(HgfsInvalidateObjectsFunc *invalidateObjects, HgfsRegisterSharedFolderFunc *registerFolder);
-
-Bool
-HgfsServerPolicy_Cleanup(void);
-
typedef uint32 HgfsShareOptions;
@@ -46,17 +40,17 @@ typedef uint32 HgfsShareOptions;
*/
typedef struct HgfsSharedFolder {
DblLnkLst_Links links;
- char *name; /* Name of share */
- char *path; /*
- * Path of share in server's filesystem. Should
- * not include final path separator.
- */
- char *shareTags; /* Tags associated with this share (comma delimited). */
- size_t shareTagsLen; /* Length of shareTag string */
- size_t nameLen; /* Length of name string */
- size_t pathLen; /* Length of path string */
- Bool readAccess; /* Read permission for this share */
- Bool writeAccess; /* Write permission for this share */
+ const char *name; /* Name of share */
+ const char *path; /*
+ * Path of share in server's filesystem. Should
+ * not include final path separator.
+ */
+ const char *shareTags;/* Tags associated with this share (comma delimited). */
+ size_t shareTagsLen; /* Length of shareTag string */
+ size_t nameLen; /* Length of name string */
+ size_t pathLen; /* Length of path string */
+ Bool readAccess; /* Read permission for this share */
+ Bool writeAccess; /* Write permission for this share */
HgfsShareOptions configOptions; /* User-config options. */
HgfsSharedFolderHandle handle; /* Handle assigned by HGFS server
* when the folder was registered with it.
@@ -78,10 +72,13 @@ typedef struct HgfsServerPolicy_ShareList {
char **shareNames;
} HgfsServerPolicy_ShareList;
-/* Defined in hgfsServerInt.h */
-HgfsGetNameFunc HgfsServerPolicy_GetShares;
-HgfsInitFunc HgfsServerPolicy_GetSharesInit;
-HgfsCleanupFunc HgfsServerPolicy_GetSharesCleanup;
+Bool
+HgfsServerPolicy_Init(HgfsInvalidateObjectsFunc invalidateObjects,
+ HgfsRegisterSharedFolderFunc registerFolder,
+ HgfsServerResEnumCallbacks *enumResources);
+
+Bool
+HgfsServerPolicy_Cleanup(void);
HgfsNameStatus
HgfsServerPolicy_GetSharePath(char const *nameIn, // IN:
diff --git a/open-vm-tools/lib/include/hgfsTransport.h b/open-vm-tools/lib/include/hgfsTransport.h
index 9ba75b19..e423ba8e 100644
--- a/open-vm-tools/lib/include/hgfsTransport.h
+++ b/open-vm-tools/lib/include/hgfsTransport.h
@@ -45,6 +45,13 @@
* VMCI specific data structures, macros *
************************************************/
+/*
+ * Limit payload to 16M.
+ * This limit ensures that list of shared pages fits into VMCI datagram.
+ * Client may impose a lower limit in create session request.
+ */
+#define HGFS_VMCI_PACKET_MAX (0x1000000)
+
#define HGFS_VMCI_VERSION_1 0x1
#define HGFS_VMCI_VERSION_2 0x2
diff --git a/open-vm-tools/lib/include/printer.h b/open-vm-tools/lib/include/hgfsUri.h
index 112cdbd0..0f718744 100644
--- a/open-vm-tools/lib/include/printer.h
+++ b/open-vm-tools/lib/include/hgfsUri.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -17,24 +17,23 @@
*********************************************************/
/*
- * printer.h --
+ * hgfsUri.h
*
- * Assorted printer related functionality.
+ * Provides a library for guest applications to convert local pathames to
+ * x-vmware-share:// style URIs
*/
-#ifndef _VM_PRINTER_H_
-#define _VM_PRINTER_H_
-
-#define INCLUDE_ALLOW_USERLEVEL
-#include "includeCheck.h"
+#ifndef _HGFS_URI_H_
+#define _HGFS_URI_H_
#include "vm_basic_types.h"
+#include "unicode.h"
-char *Printer_GetDefault(void);
-Bool Printer_SetDefault(char const *printerName); // IN
-Bool Printer_AddConnection(char *printerName, // IN: Name of printer to add
- int *sysError); // OUT: System error code (errno)
-Bool Printer_Init(void);
-Bool Printer_Cleanup(void);
+#if defined(_WIN32)
+char *HgfsUri_ConvertFromUtf16ToHgfsUri(wchar_t *pathNameUtf16, Bool hgfsOnly);
+#endif // _WIN32
+#if defined __linux__ || defined __APPLE__
+char *HgfsUri_ConvertFromPathToHgfsUri(const char *pathName, Bool hgfsOnly);
+#endif // POSIX
#endif
diff --git a/open-vm-tools/lib/include/hostType.h b/open-vm-tools/lib/include/hostType.h
index 9c2a2631..428cc850 100644
--- a/open-vm-tools/lib/include/hostType.h
+++ b/open-vm-tools/lib/include/hostType.h
@@ -34,8 +34,11 @@
#include "vm_basic_types.h"
Bool HostType_OSIsVMK(void);
-Bool HostType_OSIsPureVMK(void);
-Bool HostType_OSIsVMK64(void);
Bool HostType_OSIsSimulator(void);
+/* Old name. TODO: remove */
+static INLINE Bool
+HostType_OSIsPureVMK(void)
+{ return HostType_OSIsVMK(); }
+
#endif /* ifndef _HOSTTYPE_H_ */
diff --git a/open-vm-tools/lib/include/hostinfo.h b/open-vm-tools/lib/include/hostinfo.h
index c8b75f3e..802de140 100644
--- a/open-vm-tools/lib/include/hostinfo.h
+++ b/open-vm-tools/lib/include/hostinfo.h
@@ -43,8 +43,8 @@ typedef enum {
HostinfoProcessQuery Hostinfo_QueryProcessExistence(int pid);
-Unicode Hostinfo_NameGet(void); /* don't free result */
-Unicode Hostinfo_HostName(void); /* free result */
+char *Hostinfo_NameGet(void); /* don't free result */
+char *Hostinfo_HostName(void); /* free result */
void Hostinfo_MachineID(uint32 *hostNameHash,
uint64 *hostHardwareID);
@@ -128,10 +128,10 @@ char *Hostinfo_HypervisorCPUIDSig(void);
#define HGMP_PRIVILEGE 0
#define HGMP_NO_PRIVILEGE 1
-Unicode Hostinfo_GetModulePath(uint32 priv);
+char *Hostinfo_GetModulePath(uint32 priv);
char *Hostinfo_GetLibraryPath(void *addr);
-Unicode Hostinfo_GetUser(void);
+char *Hostinfo_GetUser(void);
void Hostinfo_LogMemUsage(void);
diff --git a/open-vm-tools/lib/include/iovector.h b/open-vm-tools/lib/include/iovector.h
index ec2991a7..7f5292ee 100644
--- a/open-vm-tools/lib/include/iovector.h
+++ b/open-vm-tools/lib/include/iovector.h
@@ -38,8 +38,8 @@
#ifndef HAS_IOVEC
struct iovec {
- void *iov_base; /* Starting address. */
- size_t iov_len; /* Length in bytes. */
+ void *iov_base; /* Starting address. */
+ size_t iov_len; /* Length in bytes. */
};
#endif // HAS_IOVEC
@@ -84,14 +84,14 @@ void IOV_MakeSingleIOV(VMIOVec* v,
uint8* buffer,
Bool read);
-void IOV_WriteIovToBuf(struct iovec* entries,
+void IOV_WriteIovToBuf(struct iovec const *entries,
int numEntries,
- uint8* bufOut,
+ uint8 *bufOut,
size_t bufSize);
-void IOV_WriteBufToIov(const uint8* bufIn,
+void IOV_WriteBufToIov(const uint8 *bufIn,
size_t bufSize,
- struct iovec* entries,
+ struct iovec const *entries,
int numEntries);
size_t
diff --git a/open-vm-tools/lib/include/log.h b/open-vm-tools/lib/include/log.h
index 5f6a61b5..f76e351e 100644
--- a/open-vm-tools/lib/include/log.h
+++ b/open-vm-tools/lib/include/log.h
@@ -30,31 +30,48 @@
/*
* The bora/lib Log Facility log level model.
- * This the same as the vmacore/hostd Log Facility.
+ *
+ * Each log entry has a level associated with it. The Log Facility filters
+ * entries as they arrive by their level; only levels equal to or below
+ * (smaller values) the filter level will be accepted by the Log Facility for
+ * processing.
+ *
+ * By default, the Log Facility will output any entry which is submitted at
+ * level VMW_LOG_WARNING and below to the "standard error". This may be
+ * controlled via Log_SetStderrLevel (see function header) or configuration
+ * parameter (see comments in log.c).
+ *
+ * The VMW_LOG_AUDIT level is used to log something that requires an audit
+ * at a later date. It is *ALWAYS* logged and *NEVER* outputs to the "standard
+ * error".
*
* The VMW_LOG_BASE is chosen to ensure that on all platforms commonly
* used system logger values will be invalid and the errant usage caught.
+ *
+ * Level Level value Comments
+ *---------------------------------------------------------------------------
*/
#define VMW_LOG_BASE 100
-#define VMW_LOG_PANIC (VMW_LOG_BASE + 0) // highest priority
-#define VMW_LOG_ERROR (VMW_LOG_BASE + 5)
-#define VMW_LOG_WARNING (VMW_LOG_BASE + 10) // <= goes to stderr by default
-#define VMW_LOG_AUDIT (VMW_LOG_BASE + 15) // *ALWAYS* output to the log
-#define VMW_LOG_INFO (VMW_LOG_BASE + 20) // <= goes to log by default
-#define VMW_LOG_VERBOSE (VMW_LOG_BASE + 25)
-#define VMW_LOG_TRIVIA (VMW_LOG_BASE + 30)
-#define VMW_LOG_DEBUG_00 (VMW_LOG_BASE + 35) // noisiest level of debugging
+#define VMW_LOG_AUDIT (VMW_LOG_BASE + 0) // ALWAYS LOGGED; NO STDERR
+#define VMW_LOG_PANIC (VMW_LOG_BASE + 5) // Quietest level
+#define VMW_LOG_ERROR (VMW_LOG_BASE + 10)
+#define VMW_LOG_WARNING (VMW_LOG_BASE + 15)
+#define VMW_LOG_NOTICE (VMW_LOG_BASE + 20)
+#define VMW_LOG_INFO (VMW_LOG_BASE + 25)
+#define VMW_LOG_VERBOSE (VMW_LOG_BASE + 30)
+#define VMW_LOG_TRIVIA (VMW_LOG_BASE + 35)
+#define VMW_LOG_DEBUG_00 (VMW_LOG_BASE + 40) // least noisy debug level
#define VMW_LOG_DEBUG_01 (VMW_LOG_DEBUG_00 + 1)
#define VMW_LOG_DEBUG_02 (VMW_LOG_DEBUG_00 + 2)
-#define VMW_LOG_DEBUG_03 (VMW_LOG_DEBUG_00 + 3)
-#define VMW_LOG_DEBUG_04 (VMW_LOG_DEBUG_00 + 4)
-#define VMW_LOG_DEBUG_05 (VMW_LOG_DEBUG_00 + 5)
-#define VMW_LOG_DEBUG_06 (VMW_LOG_DEBUG_00 + 6)
+#define VMW_LOG_DEBUG_03 (VMW_LOG_DEBUG_00 + 3) // debug levels grow
+#define VMW_LOG_DEBUG_04 (VMW_LOG_DEBUG_00 + 4) // increasingly noisy
+#define VMW_LOG_DEBUG_05 (VMW_LOG_DEBUG_00 + 5) // as the debug number
+#define VMW_LOG_DEBUG_06 (VMW_LOG_DEBUG_00 + 6) // increases
#define VMW_LOG_DEBUG_07 (VMW_LOG_DEBUG_00 + 7)
#define VMW_LOG_DEBUG_08 (VMW_LOG_DEBUG_00 + 8)
#define VMW_LOG_DEBUG_09 (VMW_LOG_DEBUG_00 + 9)
-#define VMW_LOG_DEBUG_10 (VMW_LOG_DEBUG_00 + 10) // lowest priority; least noisy
+#define VMW_LOG_DEBUG_10 (VMW_LOG_DEBUG_00 + 10) // Noisiest level
void LogV(uint32 routing,
const char *fmt,
@@ -68,10 +85,8 @@ void Log_Level(uint32 routing,
/*
* Handy wrapper functions.
*
- * Log -> VMW_LOG_INFO
+ * Log -> VMW_LOG_INFO
* Warning -> VMW_LOG_WARNING
- *
- * TODO: even Log and Warning become wrapper functions around LogV.
*/
static INLINE void PRINTF_DECL(1, 2)
@@ -111,6 +126,18 @@ Log_Error(const char *fmt,
static INLINE void PRINTF_DECL(1, 2)
+Log_Notice(const char *fmt,
+ ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ LogV(VMW_LOG_NOTICE, fmt, ap);
+ va_end(ap);
+}
+
+
+static INLINE void PRINTF_DECL(1, 2)
Log_Verbose(const char *fmt,
...)
{
@@ -163,7 +190,8 @@ LogOutput *Log_NewFileOutput(const char *appPrefix,
typedef void (LogCustomMsgFunc)(int level,
const char *msg);
-LogOutput *Log_NewCustomOutput(LogCustomMsgFunc *msgFunc,
+LogOutput *Log_NewCustomOutput(const char *instanceName,
+ LogCustomMsgFunc *msgFunc,
int minLogLevel);
Bool Log_FreeOutput(LogOutput *toOutput);
@@ -185,7 +213,7 @@ int32 Log_SetOutputLevel(LogOutput *output,
* the product should have the dependency, not an underlying library.
*
* In complex cases, where an "InitWith" is not sufficient and Log_AddOutput
- * must be used directly, the client should call Log_SetProductState, passing
+ * must be used directly, the client should call Log_SetProductInfo, passing
* the appropriate parameters, so the log file header information will be
* correct.
*/
@@ -195,19 +223,27 @@ void Log_SetProductInfo(const char *appName,
const char *buildNumber,
const char *compilationOption);
+static INLINE void
+Log_SetProductInfoSimple(void)
+{
+ Log_SetProductInfo(ProductState_GetName(),
+ ProductState_GetVersion(),
+ ProductState_GetBuildNumberString(),
+ ProductState_GetCompilationOption());
+}
+
+
LogOutput *Log_InitWithCustomInt(struct CfgInterface *cfgIf,
LogCustomMsgFunc *msgFunc,
int minLogLevel);
+
static INLINE LogOutput *
Log_InitWithCustom(struct CfgInterface *cfgIf,
LogCustomMsgFunc *msgFunc,
int minLogLevel)
{
- Log_SetProductInfo(ProductState_GetName(),
- ProductState_GetVersion(),
- ProductState_GetBuildNumberString(),
- ProductState_GetCompilationOption());
+ Log_SetProductInfoSimple();
return Log_InitWithCustomInt(cfgIf, msgFunc, minLogLevel);
}
@@ -223,10 +259,7 @@ Log_InitWithFile(const char *appPrefix,
struct CfgInterface *cfgIf,
Bool boundNumFiles)
{
- Log_SetProductInfo(ProductState_GetName(),
- ProductState_GetVersion(),
- ProductState_GetBuildNumberString(),
- ProductState_GetCompilationOption());
+ Log_SetProductInfoSimple();
return Log_InitWithFileInt(appPrefix, dict, cfgIf, boundNumFiles);
}
@@ -239,10 +272,7 @@ static INLINE LogOutput *
Log_InitWithFileSimple(const char *fileName,
const char *appPrefix)
{
- Log_SetProductInfo(ProductState_GetName(),
- ProductState_GetVersion(),
- ProductState_GetBuildNumberString(),
- ProductState_GetCompilationOption());
+ Log_SetProductInfoSimple();
return Log_InitWithFileSimpleInt(appPrefix, Log_CfgInterface(), fileName);
}
@@ -256,10 +286,7 @@ Log_InitWithSyslog(const char *appPrefix,
struct Dictionary *dict,
struct CfgInterface *cfgIf)
{
- Log_SetProductInfo(ProductState_GetName(),
- ProductState_GetVersion(),
- ProductState_GetBuildNumberString(),
- ProductState_GetCompilationOption());
+ Log_SetProductInfoSimple();
return Log_InitWithSyslogInt(appPrefix, dict, cfgIf);
}
@@ -272,17 +299,31 @@ static INLINE LogOutput *
Log_InitWithSyslogSimple(const char *syslogID,
const char *appPrefix)
{
- Log_SetProductInfo(ProductState_GetName(),
- ProductState_GetVersion(),
- ProductState_GetBuildNumberString(),
- ProductState_GetCompilationOption());
+ Log_SetProductInfoSimple();
return Log_InitWithSyslogSimpleInt(appPrefix, Log_CfgInterface(), syslogID);
}
+LogOutput *Log_InitWithStdioSimpleInt(const char *appPrefix,
+ struct CfgInterface *cfgIf,
+ const char *minLevel,
+ Bool withLinePrefix);
+
+static INLINE LogOutput *
+Log_InitWithStdioSimple(const char *appPrefix,
+ const char *minLevel,
+ Bool withLinePrefix)
+{
+ Log_SetProductInfoSimple();
+
+ return Log_InitWithStdioSimpleInt(appPrefix, Log_CfgInterface(), minLevel,
+ withLinePrefix);
+}
+
void Log_Exit(void);
Bool Log_Outputting(void);
+Bool Log_IsLevelOutputting(int level);
const char *Log_GetFileName(void);
const char *Log_GetOutputFileName(LogOutput *output);
diff --git a/open-vm-tools/lib/include/loglevel_user.h b/open-vm-tools/lib/include/loglevel_user.h
index b8a214cd..2ab1e5e8 100644
--- a/open-vm-tools/lib/include/loglevel_user.h
+++ b/open-vm-tools/lib/include/loglevel_user.h
@@ -79,9 +79,8 @@
LOGLEVEL_VAR(vusbhid), \
LOGLEVEL_VAR(vusbtablet), \
LOGLEVEL_VAR(vusbaudio), \
+ LOGLEVEL_VAR(vusbvideo),\
LOGLEVEL_VAR(hidQueue), \
- LOGLEVEL_VAR(pci_1394), \
- LOGLEVEL_VAR(1394), \
LOGLEVEL_VAR(pci_vlance), \
LOGLEVEL_VAR(pci_svga), \
LOGLEVEL_VAR(pci_e1000), \
@@ -100,8 +99,9 @@
LOGLEVEL_VAR(vcpuNUMA), \
LOGLEVEL_VAR(heci), \
LOGLEVEL_VAR(pciplugin), \
- LOGLEVEL_VAR(vmiopluginlib), \
LOGLEVEL_VAR(vsock), \
+ LOGLEVEL_VAR(vrdma), \
+ LOGLEVEL_VAR(nvdimm), \
\
/* user/disk */ \
LOGLEVEL_VAR(aioMgr), \
@@ -143,7 +143,11 @@
LOGLEVEL_VAR(mksGLContextMux), \
LOGLEVEL_VAR(mksGLDraw), \
LOGLEVEL_VAR(mksGLQuery), \
+ LOGLEVEL_VAR(mksGLTextureView), \
LOGLEVEL_VAR(mksWinBSOD), \
+ LOGLEVEL_VAR(mksDX11Renderer), \
+ LOGLEVEL_VAR(mksDX11ResourceView), \
+ LOGLEVEL_VAR(mksDX11ShimOps), \
LOGLEVEL_VAR(vdpPlugin), \
\
/* user/sound */ \
@@ -152,6 +156,9 @@
LOGLEVEL_VAR(pci_hdaudio), \
LOGLEVEL_VAR(hdaudio_alsa), \
\
+ /* user video */ \
+ LOGLEVEL_VAR(AVCapture), \
+ \
/* user/disklib */ \
LOGLEVEL_VAR(disklib), \
LOGLEVEL_VAR(dmg), \
@@ -170,6 +177,7 @@
LOGLEVEL_VAR(macbw), \
LOGLEVEL_VAR(macfi), \
LOGLEVEL_VAR(vmkcfg), \
+ LOGLEVEL_VAR(policy), \
LOGLEVEL_VAR(poll), \
LOGLEVEL_VAR(barrier), \
LOGLEVEL_VAR(mstat), \
@@ -231,8 +239,7 @@
LOGLEVEL_VAR(automation), \
LOGLEVEL_VAR(oemDevice), \
LOGLEVEL_VAR(cptOps), \
- LOGLEVEL_VAR(VProbeExec), \
- LOGLEVEL_VAR(VP), \
+ LOGLEVEL_VAR(vprobe), \
LOGLEVEL_VAR(VProbeClient), \
LOGLEVEL_VAR(device), \
LOGLEVEL_VAR(devicePowerOn), \
@@ -266,13 +273,8 @@
LOGLEVEL_VAR(serviceImpl), /* lib/serviceImpl */ \
LOGLEVEL_VAR(serviceUser), /* lib/serviceUser */ \
LOGLEVEL_VAR(ssl), \
- LOGLEVEL_VAR(vmrc), \
LOGLEVEL_VAR(namespaceDb), \
LOGLEVEL_VAR(namespaceMgr), \
- LOGLEVEL_VAR(blobMgr), \
- LOGLEVEL_VAR(vblobbe), \
- LOGLEVEL_VAR(blobFileBE), \
- LOGLEVEL_VAR(blobPythonBE), \
LOGLEVEL_VAR(grainTrack), \
LOGLEVEL_VAR(shim3D), \
LOGLEVEL_VAR(crc32), \
@@ -283,11 +285,14 @@
LOGLEVEL_VAR(vmname), /* lib/vmname */ \
LOGLEVEL_VAR(gpumgmt), \
LOGLEVEL_VAR(unityMsg), /* mks/remote/vdpUnityVmdb */ \
+ LOGLEVEL_VAR(sharedFolderMgr), /* mks/remote/vdpFolderSharedMgrVmdb */ \
LOGLEVEL_VAR(crtbora), /* apps/crtbora */ \
LOGLEVEL_VAR(mirror), \
LOGLEVEL_VAR(filtlib), \
LOGLEVEL_VAR(epd), \
+ LOGLEVEL_VAR(ddecomd), \
LOGLEVEL_VAR(hostctl), \
+ LOGLEVEL_VAR(pmemobj), \
/* end of list */
LOGLEVEL_EXTENSION_DECLARE(LOGLEVEL_USER);
diff --git a/open-vm-tools/lib/include/message.h b/open-vm-tools/lib/include/message.h
index 3637e58e..24339473 100644
--- a/open-vm-tools/lib/include/message.h
+++ b/open-vm-tools/lib/include/message.h
@@ -47,23 +47,32 @@ extern "C" {
#include "vm_basic_types.h"
-typedef struct Message_Channel Message_Channel;
+/* The channel object */
+typedef struct Message_Channel {
+ /* Identifier */
+ uint16 id;
-Message_Channel *
-Message_Open(uint32 proto); // IN
+ /* Reception buffer */
+ /* Data */
+ unsigned char *in;
+ /* Allocated size */
+ size_t inAlloc;
+ Bool inPreallocated;
-Bool
-Message_Send(Message_Channel *chan, // IN/OUT
- const unsigned char *buf, // IN
- size_t bufSize); // IN
+ /* The cookie */
+ uint32 cookieHigh;
+ uint32 cookieLow;
+} Message_Channel;
-Bool
-Message_Receive(Message_Channel *chan, // IN/OUT
- unsigned char **buf, // OUT
- size_t *bufSize); // OUT
-
-Bool
-Message_Close(Message_Channel *chan); // IN/OUT
+Bool Message_OpenAllocated(uint32 proto, Message_Channel *chan,
+ char *receiveBuffer, size_t receiveBufferSize);
+Message_Channel* Message_Open(uint32 proto);
+Bool Message_Send(Message_Channel *chan, const unsigned char *buf,
+ size_t bufSize);
+Bool Message_Receive(Message_Channel *chan, unsigned char **buf,
+ size_t *bufSize);
+Bool Message_CloseAllocated(Message_Channel *chan);
+Bool Message_Close(Message_Channel *chan);
#ifdef __cplusplus
}
diff --git a/open-vm-tools/lib/include/msg.h b/open-vm-tools/lib/include/msg.h
index a7d077ab..0f585129 100644
--- a/open-vm-tools/lib/include/msg.h
+++ b/open-vm-tools/lib/include/msg.h
@@ -114,7 +114,7 @@ VMX86_EXTERN_DATA Msg_String const Msg_RetryCancelButtons[];
VMX86_EXTERN_DATA Msg_String const Msg_OKCancelButtons[];
VMX86_EXTERN_DATA Msg_String const Msg_RetryAbortButtons[];
-extern Msg_String const Msg_Severities[];
+VMX86_EXTERN_DATA Msg_String const Msg_Severities[];
/*
diff --git a/open-vm-tools/lib/include/msgid.h b/open-vm-tools/lib/include/msgid.h
index f79ba201..9d5e493e 100644
--- a/open-vm-tools/lib/include/msgid.h
+++ b/open-vm-tools/lib/include/msgid.h
@@ -29,7 +29,7 @@
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMKERNEL
#include "includeCheck.h"
-#include "msgidDefs.h"
+#include "msgid_defs.h"
#include "vm_basic_defs.h"
diff --git a/open-vm-tools/lib/include/msgidDefs.h b/open-vm-tools/lib/include/msgid_defs.h
index e3c1fb2a..11dd6fc0 100644
--- a/open-vm-tools/lib/include/msgidDefs.h
+++ b/open-vm-tools/lib/include/msgid_defs.h
@@ -17,7 +17,7 @@
*********************************************************/
/*
- * msgidDefs.h --
+ * msgid_defs.h --
*
* Message ID magic definitions
*/
diff --git a/open-vm-tools/lib/include/mutexRankLib.h b/open-vm-tools/lib/include/mutexRankLib.h
index 6b81c36a..0c392968 100644
--- a/open-vm-tools/lib/include/mutexRankLib.h
+++ b/open-vm-tools/lib/include/mutexRankLib.h
@@ -36,15 +36,6 @@
*/
/*
- * workerLib default completion lock
- *
- * Used for workerLib callers who don't provide their own lock. Held
- * around arbitrary completion callbacks so it probably makes sense to
- * be of a low rank.
- */
-#define RANK_workerLibCmplLock RANK_libLockBase
-
-/*
* hostDeviceInfo HAL lock
*
* Must be < vmhs locks since this is held around the RANK_vmhsHDILock
@@ -76,6 +67,38 @@
#define RANK_vigorOfflineLock (RANK_libLockBase + 0x4410)
/*
+ * filtlib (must be > vigor and < disklib and workercmlp, PR 1340298)
+ */
+#define RANK_filtLibPollLock (RANK_vigorOfflineLock + 1)
+
+/*
+ * filtib lock which protects a disk's allocation bitmap state.
+ * Must be > filtLibPollLock, as it could be acquire with the poll lock held.
+ * And as evidenced by PR1437159, it must also be lower than workerLibCmplLock.
+ */
+#define RANK_filtLibAllocBitmapLock (RANK_filtLibPollLock + 1)
+
+/*
+ * workerLib default completion lock
+ *
+ * Used for workerLib callers who don't provide their own lock. Held
+ * around arbitrary completion callbacks so it makes sense to be of
+ * a low rank.
+ *
+ * Must be > RANK_vigorOfflineLock because we may queue work in Vigor
+ * offline.
+ *
+ * Must be < RANK_nfcLibLock, because NFC uses AIO Generic to perform
+ * async writes to the virtual disk.
+ *
+ * Must be > RANK_filtLibPollLock so that filtlib timers can wait
+ * for queued work.
+ *
+ * Must be > RANK_filtLibAllocBitmapLock due to PR1437159.
+ */
+#define RANK_workerLibCmplLock (RANK_filtLibAllocBitmapLock + 1)
+
+/*
* NFC lib lock
*/
#define RANK_nfcLibLock (RANK_libLockBase + 0x4505)
@@ -101,6 +124,14 @@
#define RANK_vvolLibLock (RANK_libLockBase + 0x5090)
/*
+ * Persistent-memory logical and hardware management locks
+ */
+/* The nvdimm layer is the hardware layer */
+#define RANK_nvdHandleLock (RANK_libLockBase + 0x5300)
+/* The pmem layer is the logical layer */
+#define RANK_pmemHandleLock (RANK_libLockBase + 0x5310)
+
+/*
* VMDB range:
* (RANK_libLockBase + 0x5500, RANK_libLockBase + 0x5600)
*/
diff --git a/open-vm-tools/lib/include/netutil.h b/open-vm-tools/lib/include/netutil.h
index 46951388..72940538 100644
--- a/open-vm-tools/lib/include/netutil.h
+++ b/open-vm-tools/lib/include/netutil.h
@@ -117,10 +117,10 @@ typedef struct {
* returned by said APIs.
*/
EXTERN NetUtilIfTableEntry netUtilIfTable[];
-# endif // ifdef DUMMY_NETUTIL
int NetUtil_GetIfIndex(const char *ifName);
char *NetUtil_GetIfName(int ifIndex);
+# endif // ifdef DUMMY_NETUTIL
#endif // if defined(linux)
size_t NetUtil_GetHardwareAddress(int ifIndex, // IN
diff --git a/open-vm-tools/lib/include/poll.h b/open-vm-tools/lib/include/poll.h
index 2a032928..834535ce 100644
--- a/open-vm-tools/lib/include/poll.h
+++ b/open-vm-tools/lib/include/poll.h
@@ -317,7 +317,7 @@ Bool Poll_CB_RTimeRemove(PollerFunction f,
#ifdef _WIN32
-void Poll_SetWindowMessageRecipient(HANDLE hWnd, UINT msg, Bool alwaysThunk);
+void Poll_SetWindowMessageRecipient(HWND hWnd, UINT msg, Bool alwaysThunk);
Bool Poll_FireWndCallback(void *lparam);
#endif
diff --git a/open-vm-tools/lib/include/posix.h b/open-vm-tools/lib/include/posix.h
index f0f60543..af49db5c 100644
--- a/open-vm-tools/lib/include/posix.h
+++ b/open-vm-tools/lib/include/posix.h
@@ -37,15 +37,25 @@
#include "codeset.h"
/*
- * Force all users of these wrappers to use the LFS (large file) interface
- * versions of the functions wrapper therein. If we don't do this the
- * wrappers may be built with the LFS versions and the callers might not
- * leading to a (potentially undetected) mismatch.
+ * Require the _FILE_OFFSET_BITS=64 interface, where all Posix file
+ * structures and functions are transparently 64-bit.
+ *
+ * Some OSes (FreeBSD, OS X) natively use 64-bit file offsets and
+ * will never be a problem. Other OSes (Linux, Solaris) default
+ * to 32-bit offsets in 32-bit mode. Android ... does its own thing.
+ * Windows only offers the Posix APIs as 32-bit.
+ *
+ * There are two ways of getting 64-bit offsets, defined by the LFS standard:
+ * _LARGEFILE64_SOURCE, which defines xxx64 types and functions
+ * _FILE_OFFSET_BITS=64, which replaces all types and functions
+ * The _LARGEFILE64_SOURCE strategy was transitional (late 90s) and is now
+ * deprecated. All modern code should use _FILE_OFFSET_BITS=64.
+ *
+ * Instead of checking for the exact details, check for what matters
+ * for the purposes of this file: types (e.g. off_t) must be 64-bit.
*/
-
-#if defined(linux) && !defined(__ANDROID__) && \
- (!defined(_LARGEFILE64_SOURCE) || _FILE_OFFSET_BITS != 64)
-#error LFS support is not enabled!
+#if !defined(_WIN32) && !defined(__ANDROID__)
+MY_ASSERTS(_file_offset_bits64, ASSERT_ON_COMPILE(sizeof(off_t) == 8);)
#endif
struct stat;
@@ -65,28 +75,28 @@ struct mnttab;
#endif
-int Posix_Creat(ConstUnicode pathName, mode_t mode);
-int Posix_Open(ConstUnicode pathName, int flags, ...);
-FILE *Posix_Fopen(ConstUnicode pathName, const char *mode);
-FILE *Posix_Popen(ConstUnicode pathName, const char *mode);
-int Posix_Rename(ConstUnicode fromPathName, ConstUnicode toPathName);
-int Posix_Rmdir(ConstUnicode pathName);
-int Posix_Unlink(ConstUnicode pathName);
-FILE *Posix_Freopen(ConstUnicode pathName, const char *mode, FILE *stream);
-int Posix_Access(ConstUnicode pathName, int mode);
-int Posix_EuidAccess(ConstUnicode pathName, int mode);
-int Posix_Stat(ConstUnicode pathName, struct stat *statbuf);
-int Posix_Chmod(ConstUnicode pathName, mode_t mode);
-void Posix_Perror(ConstUnicode str);
-int Posix_Printf(ConstUnicode format, ...);
-int Posix_Fprintf(FILE *stream, ConstUnicode format, ...);
-
-int Posix_Mkdir(ConstUnicode pathName, mode_t mode);
-int Posix_Chdir(ConstUnicode pathName);
-Unicode Posix_Getenv(ConstUnicode name);
-long Posix_Pathconf(ConstUnicode pathName, int name);
-int Posix_Lstat(ConstUnicode pathName, struct stat *statbuf);
-Unicode Posix_MkTemp(ConstUnicode pathName);
+int Posix_Creat(const char *pathName, mode_t mode);
+int Posix_Open(const char *pathName, int flags, ...);
+FILE *Posix_Fopen(const char *pathName, const char *mode);
+FILE *Posix_Popen(const char *pathName, const char *mode);
+int Posix_Rename(const char *fromPathName, const char *toPathName);
+int Posix_Rmdir(const char *pathName);
+int Posix_Unlink(const char *pathName);
+FILE *Posix_Freopen(const char *pathName, const char *mode, FILE *stream);
+int Posix_Access(const char *pathName, int mode);
+int Posix_EuidAccess(const char *pathName, int mode);
+int Posix_Stat(const char *pathName, struct stat *statbuf);
+int Posix_Chmod(const char *pathName, mode_t mode);
+void Posix_Perror(const char *str);
+int Posix_Printf(const char *format, ...);
+int Posix_Fprintf(FILE *stream, const char *format, ...);
+
+int Posix_Mkdir(const char *pathName, mode_t mode);
+int Posix_Chdir(const char *pathName);
+char *Posix_Getenv(const char *name);
+long Posix_Pathconf(const char *pathName, int name);
+int Posix_Lstat(const char *pathName, struct stat *statbuf);
+char *Posix_MkTemp(const char *pathName);
#if !defined(_WIN32)
/*
@@ -101,28 +111,28 @@ Unicode Posix_MkTemp(ConstUnicode pathName);
#define Posix_FreeAddrInfo freeaddrinfo
#define Posix_GetNameInfo getnameinfo
-void *Posix_Dlopen(ConstUnicode pathName, int flags);
-
-int Posix_Utime(ConstUnicode pathName, const struct utimbuf *times);
-
-int Posix_Mknod(ConstUnicode pathName, mode_t mode, dev_t dev);
-int Posix_Chown(ConstUnicode pathName, uid_t owner, gid_t group);
-int Posix_Lchown(ConstUnicode pathName, uid_t owner, gid_t group);
-int Posix_Link(ConstUnicode pathName1, ConstUnicode pathName2);
-int Posix_Symlink(ConstUnicode pathName1, ConstUnicode pathName2);
-int Posix_Mkfifo(ConstUnicode pathName, mode_t mode);
-int Posix_Truncate(ConstUnicode pathName, off_t length);
-int Posix_Utimes(ConstUnicode pathName, const struct timeval *time);
-int Posix_Execl(ConstUnicode pathName, ConstUnicode arg0, ...);
-int Posix_Execlp(ConstUnicode fileName, ConstUnicode arg0, ...);
-int Posix_Execv(ConstUnicode pathName, Unicode const argVal[]);
-int Posix_Execve(ConstUnicode pathName, Unicode const argVal[],
- Unicode const envPtr[]);
-int Posix_Execvp(ConstUnicode fileName, Unicode const argVal[]);
-DIR *Posix_OpenDir(ConstUnicode pathName);
-int Posix_System(ConstUnicode command);
-int Posix_Putenv(Unicode name);
-void Posix_Unsetenv(ConstUnicode name);
+void *Posix_Dlopen(const char *pathName, int flags);
+
+int Posix_Utime(const char *pathName, const struct utimbuf *times);
+
+int Posix_Mknod(const char *pathName, mode_t mode, dev_t dev);
+int Posix_Chown(const char *pathName, uid_t owner, gid_t group);
+int Posix_Lchown(const char *pathName, uid_t owner, gid_t group);
+int Posix_Link(const char *pathName1, const char *pathName2);
+int Posix_Symlink(const char *pathName1, const char *pathName2);
+int Posix_Mkfifo(const char *pathName, mode_t mode);
+int Posix_Truncate(const char *pathName, off_t length);
+int Posix_Utimes(const char *pathName, const struct timeval *time);
+int Posix_Execl(const char *pathName, const char *arg0, ...);
+int Posix_Execlp(const char *fileName, const char *arg0, ...);
+int Posix_Execv(const char *pathName, char *const argVal[]);
+int Posix_Execve(const char *pathName, char *const argVal[],
+ char *const envPtr[]);
+int Posix_Execvp(const char *fileName, char *const argVal[]);
+DIR *Posix_OpenDir(const char *pathName);
+int Posix_System(const char *command);
+int Posix_Putenv(char *name);
+void Posix_Unsetenv(const char *name);
/*
* These functions return dynamically allocated stings that have to be
@@ -130,35 +140,35 @@ void Posix_Unsetenv(ConstUnicode name);
* are different than their POSIX "base" functions.
*/
-Unicode Posix_RealPath(ConstUnicode pathName);
-Unicode Posix_ReadLink(ConstUnicode pathName);
+char *Posix_RealPath(const char *pathName);
+char *Posix_ReadLink(const char *pathName);
-struct passwd *Posix_Getpwnam(ConstUnicode name);
+struct passwd *Posix_Getpwnam(const char *name);
struct passwd *Posix_Getpwuid(uid_t uid);
-int Posix_Setenv(ConstUnicode name, ConstUnicode value, int overWrite);
+int Posix_Setenv(const char *name, const char *value, int overWrite);
-int Posix_Getpwnam_r(ConstUnicode name, struct passwd *pw,
+int Posix_Getpwnam_r(const char *name, struct passwd *pw,
char *buf, size_t size, struct passwd **ppw);
int Posix_Getpwuid_r(uid_t uid, struct passwd *pw,
char *buf, size_t size, struct passwd **ppw);
struct passwd *Posix_Getpwent(void);
-struct group *Posix_Getgrnam(ConstUnicode name);
-int Posix_Getgrnam_r(ConstUnicode name, struct group *gr,
+struct group *Posix_Getgrnam(const char *name);
+int Posix_Getgrnam_r(const char *name, struct group *gr,
char *buf, size_t size, struct group **pgr);
#if !defined(sun)
-int Posix_Statfs(ConstUnicode pathName, struct statfs *statfsbuf);
+int Posix_Statfs(const char *pathName, struct statfs *statfsbuf);
-int Posix_GetGroupList(ConstUnicode user, gid_t group, gid_t *groups,
+int Posix_GetGroupList(const char *user, gid_t group, gid_t *groups,
int *ngroups);
#if !defined(__APPLE__) && !defined(__FreeBSD__)
-int Posix_Mount(ConstUnicode source, ConstUnicode target,
+int Posix_Mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data);
-int Posix_Umount(ConstUnicode target);
-FILE *Posix_Setmntent(ConstUnicode pathName, const char *mode);
+int Posix_Umount(const char *target);
+FILE *Posix_Setmntent(const char *pathName, const char *mode);
struct mntent *Posix_Getmntent(FILE *fp);
struct mntent *Posix_Getmntent_r(FILE *fp, struct mntent *m,
char *buf, int size);
@@ -179,7 +189,7 @@ int Posix_Getmntent(FILE *fp, struct mnttab *mp);
* Wrapper for gethostbyname(). Caller should release memory
* allocated for the hostent structure returned by calling
* Posix_FreeHostent().
- *
+ *
* Results:
* NULL Error
* !NULL Pointer to hostent structure
@@ -191,7 +201,7 @@ int Posix_Getmntent(FILE *fp, struct mnttab *mp);
*/
static INLINE struct hostent*
-Posix_GetHostByName(ConstUnicode name) // IN
+Posix_GetHostByName(const char *name) // IN
{
struct hostent *newhostent;
int error;
@@ -206,7 +216,7 @@ Posix_GetHostByName(ConstUnicode name) // IN
if ((gethostbyname_r(name, &he, buffer, sizeof buffer,
#if !defined(sun) && !defined(SOLARIS) && !defined(SOL10)
- &phe,
+ &phe,
#endif
&error) == 0) && phe) {
@@ -227,7 +237,7 @@ Posix_GetHostByName(ConstUnicode name) // IN
for (p = phe->h_addr_list; *p; p++) {
naddrs++;
}
- newhostent->h_addr_list = (char **)Util_SafeMalloc(naddrs *
+ newhostent->h_addr_list = (char **)Util_SafeMalloc(naddrs *
sizeof(*(phe->h_addr_list)));
for (i = 0; i < naddrs - 1; i++) {
newhostent->h_addr_list[i] = (char *)Util_SafeMalloc(phe->h_length);
@@ -235,7 +245,7 @@ Posix_GetHostByName(ConstUnicode name) // IN
}
newhostent->h_addr_list[naddrs - 1] = NULL;
return newhostent;
- }
+ }
/* There has been an error */
return NULL;
}
@@ -266,9 +276,9 @@ Posix_FreeHostent(struct hostent *he)
char **p;
if (he) {
- Unicode_Free(he->h_name);
+ free(he->h_name);
if (he->h_aliases) {
- Unicode_FreeList(he->h_aliases, -1);
+ Util_FreeStringList(he->h_aliases, -1);
}
p = he->h_addr_list;
while (*p) {
@@ -307,11 +317,11 @@ Posix_FreeHostent(struct hostent *he)
*/
static INLINE int
-Posix_GetHostName(Unicode name, // OUT
+Posix_GetHostName(char *name, // OUT
int namelen) // IN
{
char *nameMBCS = (char *)Util_SafeMalloc(namelen);
- Unicode nameUTF8;
+ char *nameUTF8;
int retval;
ASSERT(name);
@@ -325,11 +335,11 @@ Posix_GetHostName(Unicode name, // OUT
retval = -1;
WSASetLastError(WSAEFAULT);
}
- Unicode_Free(nameUTF8);
+ free(nameUTF8);
}
free(nameMBCS);
-
+
return retval;
}
@@ -342,7 +352,7 @@ Posix_GetHostName(Unicode name, // OUT
* Wrapper for gethostbyname(). Caller should release memory
* allocated for the hostent structure returned by calling
* Posix_FreeHostent().
- *
+ *
* Results:
* NULL Error
* !NULL Pointer to hostent structure
@@ -354,7 +364,7 @@ Posix_GetHostName(Unicode name, // OUT
*/
static INLINE struct hostent*
-Posix_GetHostByName(ConstUnicode name) // IN
+Posix_GetHostByName(const char *name) // IN
{
struct hostent *newhostent;
char *nameMBCS;
@@ -416,9 +426,9 @@ static INLINE void
Posix_FreeHostent(struct hostent *he)
{
if (he) {
- Unicode_Free(he->h_name);
+ free(he->h_name);
if (he->h_aliases) {
- Unicode_FreeList(he->h_aliases, -1);
+ Util_FreeStringList(he->h_aliases, -1);
}
free(he);
}
@@ -457,8 +467,8 @@ typedef int (WINAPI *GetNameInfoWFnType)(const SOCKADDR *pSockaddr,
*/
static INLINE int
-Posix_GetAddrInfo(ConstUnicode nodename, // IN
- ConstUnicode servname, // IN
+Posix_GetAddrInfo(const char *nodename, // IN
+ const char *servname, // IN
const struct addrinfo *hints, // IN
struct addrinfo **res) // OUT
{
@@ -621,13 +631,13 @@ Posix_FreeAddrInfo(struct addrinfo *ai)
*/
static INLINE int
-Posix_GetNameInfo(const struct sockaddr *sa, // IN
- socklen_t salen, // IN
- Unicode host, // OUT
- DWORD hostlen, // IN
- Unicode serv, // OUT
- DWORD servlen, // IN
- int flags) // IN
+Posix_GetNameInfo(const struct sockaddr *sa, // IN
+ socklen_t salen, // IN
+ char *host, // OUT
+ DWORD hostlen, // IN
+ char *serv, // OUT
+ DWORD servlen, // IN
+ int flags) // IN
{
HMODULE hWs2_32;
int retval;
@@ -635,8 +645,8 @@ Posix_GetNameInfo(const struct sockaddr *sa, // IN
char *servMBCS = NULL;
utf16_t *hostW = NULL;
utf16_t *servW = NULL;
- Unicode hostUTF8 = NULL;
- Unicode servUTF8 = NULL;
+ char *hostUTF8 = NULL;
+ char *servUTF8 = NULL;
GetNameInfoWFnType GetNameInfoWFn;
hWs2_32 = LoadLibraryW(L"ws2_32");
@@ -683,7 +693,7 @@ Posix_GetNameInfo(const struct sockaddr *sa, // IN
}
}
}
-
+
goto exit;
}
}
diff --git a/open-vm-tools/lib/include/productState.h b/open-vm-tools/lib/include/productState.h
index a5196a18..ab7ea7de 100644
--- a/open-vm-tools/lib/include/productState.h
+++ b/open-vm-tools/lib/include/productState.h
@@ -44,13 +44,17 @@ typedef enum {
PRODUCT_CVP = 1 << 5,
PRODUCT_FUSION = 1 << 6,
PRODUCT_VIEW = 1 << 7,
+ PRODUCT_VMRC = 1 << 8,
+ PRODUCT_GANTRY = 1 << 9,
/* etc */
} Product;
typedef uint64 ProductMask;
#define PRODUCTMASK_HOSTED (PRODUCT_WORKSTATION |\
PRODUCT_PLAYER |\
PRODUCT_CVP |\
- PRODUCT_FUSION)
+ PRODUCT_FUSION |\
+ PRODUCT_VMRC |\
+ PRODUCT_GANTRY)
typedef uint64 ProductCaps;
/*
@@ -85,6 +89,7 @@ void ProductState_Set(Product product, const char *name, const char *version,
Product ProductState_GetProduct(void);
Bool ProductState_IsProduct(ProductMask product);
+Bool ProductState_AllowUnlicensedVMX(void);
const char *ProductState_GetName(void);
const char *ProductState_GetVersion(void);
unsigned int ProductState_GetBuildNumber(void);
diff --git a/open-vm-tools/lib/include/rpcout.h b/open-vm-tools/lib/include/rpcout.h
index 517edca0..654de943 100644
--- a/open-vm-tools/lib/include/rpcout.h
+++ b/open-vm-tools/lib/include/rpcout.h
@@ -63,15 +63,25 @@ Bool RpcOut_stop(RpcOut *out);
Bool RpcOut_sendOne(char **reply, size_t *repLen, char const *reqFmt, ...);
/*
- * A new version of the above function that works with UTF-8 strings
- * and other data that would be corrupted by Win32's FormatMessage
- * function (which is used by RpcOut_sendOne()).
+ * A version of the RpcOut_sendOne function that works with UTF-8
+ * strings and other data that would be corrupted by Win32's
+ * FormatMessage function (which is used by RpcOut_sendOne()).
*/
Bool RpcOut_SendOneRaw(void *request, size_t reqLen, char **reply, size_t *repLen);
+/*
+ * A variant of the RpcOut_SendOneRaw in which the caller supplies the
+ * receive buffer so as to avoid the need to call malloc internally.
+ * Useful in situations where calling malloc is not allowed.
+ */
+
+Bool RpcOut_SendOneRawPreallocated(void *request, size_t reqLen, char *reply,
+ size_t repLen);
+
/*
- * As the above but must be run by admin/root to make the privileged RPC call successfully.
+ * As the above but must be run by admin/root to make the privileged
+ * RPC call successfully.
*/
Bool RpcOut_SendOneRawPriv(void *request, size_t reqLen, char **reply, size_t *repLen);
diff --git a/open-vm-tools/lib/include/sha1.h b/open-vm-tools/lib/include/sha1.h
index ae5fd3ae..90df3619 100644
--- a/open-vm-tools/lib/include/sha1.h
+++ b/open-vm-tools/lib/include/sha1.h
@@ -67,6 +67,22 @@
#else
+#ifndef VMKERNEL
+
+/*
+ * Prevent linkage conflicts with the SHA1 APIs brought in from
+ * OpenSSL. (Pro tip: If you're doing anything security-related, you
+ * _must_ be using lib/crypto hash routines to preserve FIPS
+ * compatibility.)
+ */
+
+#define SHA1Init VMW_SHA1Init
+#define SHA1Update VMW_SHA1Update
+#define SHA1Final VMW_SHA1Final
+#define SHA1RawBufferHash VMW_SHA1RawBufferHash
+
+#endif /* !VMKERNEL */
+
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
@@ -94,20 +110,16 @@ typedef struct {
unsigned char buffer[64];
} SHA1_CTX;
-#define SHA1HANDSOFF /* Copies data before messing with it. */
-
void SHA1Init(SHA1_CTX* context);
-#ifdef SHA1HANDSOFF
void SHA1Update(SHA1_CTX* context,
const unsigned char *data,
size_t len);
-#else
-void SHA1Update(SHA1_CTX* context,
- unsigned char *data,
- size_t len);
-#endif
void SHA1Final(unsigned char digest[SHA1_HASH_LEN], SHA1_CTX* context);
+void SHA1RawBufferHash(const void *data,
+ uint32 size,
+ uint32 result[5]);
+
#endif // defined __APPLE__ && defined USERLEVEL
#endif // ifndef _SHA1_H_
diff --git a/open-vm-tools/lib/include/sigPosixRegs.h b/open-vm-tools/lib/include/sigPosixRegs.h
index cff468bd..08ee2c6e 100644
--- a/open-vm-tools/lib/include/sigPosixRegs.h
+++ b/open-vm-tools/lib/include/sigPosixRegs.h
@@ -270,6 +270,10 @@
#define SC_SP(uc) ((unsigned long) (uc)->uc_mcontext.arm_sp)
#define SC_LR(uc) ((unsigned long) (uc)->uc_mcontext.arm_lr)
#define SC_PC(uc) ((unsigned long) (uc)->uc_mcontext.arm_pc)
+#elif defined(__aarch64__)
+#define SC_X(uc,n) ((unsigned long) (uc)->uc_mcontext.regs[n])
+#define SC_SP(uc) ((unsigned long) (uc)->uc_mcontext.sp)
+#define SC_PC(uc) ((unsigned long) (uc)->uc_mcontext.pc)
#else
#define SC_EAX(uc) ((unsigned long) (uc)->uc_mcontext.gregs[GNU_REG_EAX])
#define SC_EBX(uc) ((unsigned long) (uc)->uc_mcontext.gregs[GNU_REG_EBX])
diff --git a/open-vm-tools/lib/include/sslDirect.h b/open-vm-tools/lib/include/sslDirect.h
index bbf7c094..a635983c 100644
--- a/open-vm-tools/lib/include/sslDirect.h
+++ b/open-vm-tools/lib/include/sslDirect.h
@@ -29,7 +29,7 @@
#define INCLUDE_ALLOW_USERLEVEL
#include "includeCheck.h"
-
+typedef struct _SSLVerifyParam SSLVerifyParam;
typedef struct SSLSockStruct *SSLSock;
typedef char* (SSLLibFn)(const char*, const char*);
diff --git a/open-vm-tools/lib/include/str.h b/open-vm-tools/lib/include/str.h
index 88ec701c..e6c50a65 100644
--- a/open-vm-tools/lib/include/str.h
+++ b/open-vm-tools/lib/include/str.h
@@ -89,30 +89,53 @@
*/
#ifdef HAS_BSD_PRINTF
-int Str_Sprintf_C_Locale(char *buf, size_t max,
- const char *fmt, ...) PRINTF_DECL(3, 4);
+int Str_Sprintf_C_Locale(char *buf, // OUT:
+ size_t max, // IN:
+ const char *fmt, // IN:
+ ...) PRINTF_DECL(3, 4); // IN:
#endif
-int Str_Sprintf(char *buf, size_t max,
- const char *fmt, ...) PRINTF_DECL(3, 4);
-int Str_Snprintf(char *buf, size_t len,
- const char *fmt, ...) PRINTF_DECL(3, 4);
-int Str_Vsnprintf(char *buf, size_t len,
- const char *fmt, va_list args);
-size_t Str_Strlen(const char *src, size_t maxLen);
-char *Str_Strnstr(const char *src, const char *sub, size_t n);
-char *Str_Strcpy(char *dst, const char *src, size_t maxLen);
-char *Str_Strcat(char *dst, const char *src, size_t maxLen);
-char *Str_Strncat(char *buf, size_t bufSize, const char *src, size_t n);
-
-char *Str_Asprintf(size_t *length,
- const char *format, ...) PRINTF_DECL(2, 3);
-char *Str_Vasprintf(size_t *length, const char *format,
- va_list arguments);
-char *Str_SafeAsprintf(size_t *length,
- const char *format, ...) PRINTF_DECL(2, 3);
-char *Str_SafeVasprintf(size_t *length, const char *format,
- va_list arguments);
+int Str_Sprintf(char *buf, // OUT:
+ size_t max, // IN:
+ const char *fmt, // IN:
+ ...) PRINTF_DECL(3, 4); // IN:
+int Str_Snprintf(char *buf, // OUT:
+ size_t len, // IN:
+ const char *fmt, // IN:
+ ...) PRINTF_DECL(3, 4); // IN:
+int Str_Vsnprintf(char *buf, // OUT:
+ size_t len, // IN:
+ const char *fmt, // IN:
+ va_list args); // IN:
+
+size_t Str_Strlen(const char *src, // IN:
+ size_t maxLen); // IN:
+char *Str_Strnstr(const char *src, // IN:
+ const char *sub, // IN:
+ size_t n); // IN:
+char *Str_Strcpy(char *dst, // OUT:
+ const char *src, // IN:
+ size_t maxLen); // IN:
+char *Str_Strcat(char *dst, // IN/OUT:
+ const char *src, // IN:
+ size_t maxLen); // IN:
+char *Str_Strncat(char *buf, // IN/OUT:
+ size_t bufSize, // IN:
+ const char *src, // IN:
+ size_t n); // IN:
+
+char *Str_Asprintf(size_t *length, // OUT/OPT:
+ const char *format, // IN:
+ ...) PRINTF_DECL(2, 3); // IN:
+char *Str_Vasprintf(size_t *length, // OUT/OPT:
+ const char *format, // IN:
+ va_list arguments); // IN:
+char *Str_SafeAsprintf(size_t *length, // OUT/OPT:
+ const char *format, // IN:
+ ...) PRINTF_DECL(2, 3); // IN:
+char *Str_SafeVasprintf(size_t *length, // OUT/OPT:
+ const char *format, // IN:
+ va_list arguments); // IN:
#if defined(_WIN32) || defined(__linux__) // {
@@ -129,30 +152,48 @@ char *Str_SafeVasprintf(size_t *length, const char *format,
* strings of "wchar_t" units, regardless of platform.
*/
-int Str_Swprintf(wchar_t *buf, size_t max,
- const wchar_t *fmt, ...);
-int Str_Snwprintf(wchar_t *buf, size_t len,
- const wchar_t *fmt, ...);
-int Str_Vsnwprintf(wchar_t *buf, size_t len,
- const wchar_t *fmt, va_list args);
-wchar_t *Str_Wcscpy(wchar_t *dst, const wchar_t *src, size_t maxLen);
-wchar_t *Str_Wcscat(wchar_t *dst, const wchar_t *src, size_t maxLen);
-wchar_t *Str_Wcsncat(wchar_t *buf, size_t bufSize, const wchar_t *src,
- size_t n);
-
-wchar_t *Str_Aswprintf(size_t *length,
- const wchar_t *format, ...);
-wchar_t *Str_Vaswprintf(size_t *length, const wchar_t *format,
- va_list arguments);
-wchar_t *Str_SafeAswprintf(size_t *length,
- const wchar_t *format, ...);
-wchar_t *Str_SafeVaswprintf(size_t *length, const wchar_t *format,
- va_list arguments);
-
-unsigned char *Str_Mbscpy(char *buf, const char *src,
- size_t maxSize);
-unsigned char *Str_Mbscat(char *buf, const char *src,
- size_t maxSize);
+int Str_Swprintf(wchar_t *buf, // OUT:
+ size_t max, // IN:
+ const wchar_t *fmt, // IN:
+ ...);
+int Str_Snwprintf(wchar_t *buf, // OUT:
+ size_t len, // IN:
+ const wchar_t *fmt, // IN:
+ ...);
+int Str_Vsnwprintf(wchar_t *buf, // OUT:
+ size_t len, // IN:
+ const wchar_t *fmt, // IN:
+ va_list args);
+wchar_t *Str_Wcscpy(wchar_t *dst, // OUT:
+ const wchar_t *src, // IN:
+ size_t maxLen); // IN:
+wchar_t *Str_Wcscat(wchar_t *dst, // IN/OUT:
+ const wchar_t *src, // IN:
+ size_t maxLen); // IN:
+wchar_t *Str_Wcsncat(wchar_t *buf, // IN/OUT:
+ size_t bufSize, // IN:
+ const wchar_t *src, // IN:
+ size_t n); // IN:
+
+wchar_t *Str_Aswprintf(size_t *length, // OUT/OPT:
+ const wchar_t *format, // IN:
+ ...); // IN:
+wchar_t *Str_Vaswprintf(size_t *length, // OUT/OPT:
+ const wchar_t *format, // IN:
+ va_list arguments); // IN:
+wchar_t *Str_SafeAswprintf(size_t *length, // OUT/OPT:
+ const wchar_t *format, // IN:
+ ...); // IN:
+wchar_t *Str_SafeVaswprintf(size_t *length, // OUT/OPT:
+ const wchar_t *format, // IN:
+ va_list arguments); // IN:
+
+unsigned char *Str_Mbscpy(char *buf, // OUT:
+ const char *src, // IN:
+ size_t maxSize); // IN:
+unsigned char *Str_Mbscat(char *buf, // IN/OUT:
+ const char *src, // IN:
+ size_t maxSize); // IN:
/*
* These are handly for Windows programmers. They are like
diff --git a/open-vm-tools/lib/include/system.h b/open-vm-tools/lib/include/system.h
index 6f937606..d91f26fe 100644
--- a/open-vm-tools/lib/include/system.h
+++ b/open-vm-tools/lib/include/system.h
@@ -36,7 +36,7 @@
uint64 System_GetTimeMonotonic(void);
uint64 System_Uptime(void);
-Unicode System_GetTimeAsString(void);
+char *System_GetTimeAsString(void);
void System_Shutdown(Bool reboot);
Bool System_GetNodeName(size_t outBufSize, char *outBuf);
diff --git a/open-vm-tools/lib/include/unicodeBase.h b/open-vm-tools/lib/include/unicodeBase.h
index 2b317822..0cffbe33 100644
--- a/open-vm-tools/lib/include/unicodeBase.h
+++ b/open-vm-tools/lib/include/unicodeBase.h
@@ -55,7 +55,7 @@ extern "C" {
*
* with:
*
- * ConstUnicode copyright = U_UNESCAPE("Copyright \\u00A9 COMPANY_NAME");
+ * const char *copyright = U_UNESCAPE("Copyright \\u00A9 COMPANY_NAME");
*/
#define U_UNESCAPE(x) Unicode_GetStatic(x, TRUE)
@@ -79,7 +79,7 @@ extern "C" {
* allocated.
*/
-Unicode Unicode_AllocWithLength(const void *buffer,
+char *Unicode_AllocWithLength(const void *buffer,
ssize_t lengthInBytes,
StringEncoding encoding);
@@ -100,7 +100,7 @@ Unicode Unicode_AllocWithLength(const void *buffer,
* Results:
* An allocated Unicode string containing the decoded characters
* in buffer, or NULL if input is NULL. Caller must pass to
- * Unicode_Free to free.
+ * free to free.
*
* Side effects:
* None
@@ -108,7 +108,7 @@ Unicode Unicode_AllocWithLength(const void *buffer,
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
+static INLINE char *
Unicode_Alloc(const void *buffer, // IN
StringEncoding encoding) // IN
{
@@ -128,7 +128,7 @@ Unicode_Alloc(const void *buffer, // IN
* Results:
* An allocated Unicode string containing the characters in
* utf8String, or NULL if utf8String is NULL. Caller must pass to
- * Unicode_Free to free.
+ * free to free.
*
* Side effects:
* None
@@ -136,7 +136,7 @@ Unicode_Alloc(const void *buffer, // IN
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
+static INLINE char *
Unicode_AllocWithUTF8(const char *utf8String) // IN
{
return Unicode_AllocWithLength(utf8String, -1, STRING_ENCODING_UTF8);
@@ -156,7 +156,7 @@ Unicode_AllocWithUTF8(const char *utf8String) // IN
* Results:
* An allocated Unicode string containing the characters in
* utf16String, or NULL if utf16String is NULL. Caller must pass to
- * Unicode_Free to free.
+ * free to free.
*
* Side effects:
* None
@@ -164,21 +164,19 @@ Unicode_AllocWithUTF8(const char *utf8String) // IN
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
+static INLINE char *
Unicode_AllocWithUTF16(const utf16_t *utf16String) // IN
{
return Unicode_AllocWithLength(utf16String, -1, STRING_ENCODING_UTF16);
}
-Unicode Unicode_Duplicate(ConstUnicode str);
-void Unicode_Free(void *str);
+char *Unicode_Duplicate(const char *str);
-
-Unicode *Unicode_AllocList(char **srcList, ssize_t length,
+char **Unicode_AllocList(char **srcList, ssize_t length,
StringEncoding encoding);
-char **Unicode_GetAllocList(Unicode const srcList[], ssize_t length,
+char **Unicode_GetAllocList(char *const srcList[], ssize_t length,
StringEncoding encoding);
/*
@@ -192,7 +190,7 @@ char **Unicode_GetAllocList(Unicode const srcList[], ssize_t length,
*
* Results:
* An allocated list (vector) of Unicode strings.
- * The result must be freed with Unicode_FreeList.
+ * The result must be freed with Util_FreeStringList.
*
* Side effects:
* None
@@ -200,7 +198,7 @@ char **Unicode_GetAllocList(Unicode const srcList[], ssize_t length,
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode *
+static INLINE char **
Unicode_AllocListWithUTF16(utf16_t **utf16list, // IN:
ssize_t length) // IN:
{
@@ -208,27 +206,6 @@ Unicode_AllocListWithUTF16(utf16_t **utf16list, // IN:
STRING_ENCODING_UTF16);
}
-void Unicode_FreeList(Unicode *list, ssize_t length);
-
-
-/*
- * Accessor for the NUL-terminated UTF-8 representation of this
- * Unicode string.
- *
- * Memory is managed inside this string, so callers do not need to
- * free.
- */
-const char *Unicode_GetUTF8(ConstUnicode str);
-
-/*
- * Convenience wrapper with a short name for this often-used function.
- */
-static INLINE const char *
-UTF8(ConstUnicode str)
-{
- return Unicode_GetUTF8(str);
-}
-
/*
* Compute the number of bytes in a string.
*/
@@ -255,7 +232,7 @@ Bool Unicode_IsBufferValid(const void *buffer,
* Tests if the buffer's unicode contents can be converted to the
* specified encoding.
*/
-Bool Unicode_CanGetBytesWithEncoding(ConstUnicode ustr,
+Bool Unicode_CanGetBytesWithEncoding(const char *ustr,
StringEncoding encoding);
/*
@@ -270,7 +247,7 @@ char *Unicode_EscapeBuffer(const void *buffer,
* Returns the length in number of native code units (UTF-8 bytes or
* UTF-16 words) of the string.
*/
-UnicodeIndex Unicode_LengthInCodeUnits(ConstUnicode str);
+UnicodeIndex Unicode_LengthInCodeUnits(const char *str);
/*
*-----------------------------------------------------------------------------
@@ -289,14 +266,10 @@ UnicodeIndex Unicode_LengthInCodeUnits(ConstUnicode str);
*/
static INLINE Bool
-Unicode_IsEmpty(ConstUnicode str) // IN:
+Unicode_IsEmpty(const char *str) // IN:
{
-#ifdef SUPPORT_UNICODE_OPAQUE
- NOT_IMPLEMENTED();
-#else
ASSERT(str != NULL);
return str[0] == '\0';
-#endif
}
@@ -305,7 +278,7 @@ Unicode_IsEmpty(ConstUnicode str) // IN:
* to encode the Unicode string in the specified encoding, including
* NUL termination.
*/
-size_t Unicode_BytesRequired(ConstUnicode str,
+size_t Unicode_BytesRequired(const char *str,
StringEncoding encoding);
/*
@@ -317,15 +290,15 @@ size_t Unicode_BytesRequired(ConstUnicode str,
* the NUL termination, upon return.
*/
Bool Unicode_CopyBytes(void *destBuffer,
- ConstUnicode srcBuffer,
+ const char *srcBuffer,
size_t maxLengthInBytes,
size_t *retLength,
StringEncoding encoding);
-void *Unicode_GetAllocBytes(ConstUnicode str,
+void *Unicode_GetAllocBytes(const char *str,
StringEncoding encoding);
-void *Unicode_GetAllocBytesWithLength(ConstUnicode str,
+void *Unicode_GetAllocBytesWithLength(const char *str,
StringEncoding encoding,
ssize_t lengthInBytes);
@@ -354,7 +327,7 @@ void *Unicode_GetAllocBytesWithLength(ConstUnicode str,
*/
static INLINE utf16_t *
-Unicode_GetAllocUTF16(ConstUnicode str) // IN:
+Unicode_GetAllocUTF16(const char *str) // IN:
{
/* Cast for compatibility with C++ compilers. */
return (utf16_t *) Unicode_GetAllocBytes(str, STRING_ENCODING_UTF16);
@@ -364,21 +337,11 @@ Unicode_GetAllocUTF16(ConstUnicode str) // IN:
/*
* Helper function for Unicode string literal macros.
*/
-ConstUnicode Unicode_GetStatic(const char *asciiBytes,
- Bool unescape);
+const char *Unicode_GetStatic(const char *asciiBytes,
+ Bool unescape);
/*
* Helper macros for Win32 Unicode string transition.
- *
- * Eventually, when the Unicode type becomes opaque
- * (SUPPORT_UNICODE_OPAQUE), we can store UTF-16 directly inside
- * it, which is a huge optimization for Win32 programmers.
- *
- * At that point, UNICODE_GET_UTF16/UNICODE_RELEASE_UTF16 can become
- * constant-time operations.
- *
- * Until then, Win32 programmers need to alloc and free the UTF-16
- * representation of the Unicode string.
*/
#if defined(_WIN32)
#define UNICODE_GET_UTF16(s) Unicode_GetAllocUTF16(s)
diff --git a/open-vm-tools/lib/include/unicodeICU.h b/open-vm-tools/lib/include/unicodeICU.h
index 05b46b99..1bf9bd07 100644
--- a/open-vm-tools/lib/include/unicodeICU.h
+++ b/open-vm-tools/lib/include/unicodeICU.h
@@ -60,8 +60,8 @@ typedef enum {
* the user's language and culture, collectively called the "locale".
*/
-int Unicode_CompareWithLocale(ConstUnicode str1,
- ConstUnicode str2,
+int Unicode_CompareWithLocale(const char *str1,
+ const char *str2,
const char *locale,
UnicodeCompareOption compareOption);
@@ -73,11 +73,11 @@ int Unicode_CompareWithLocale(ConstUnicode str1,
* Changing the case of a string can change its length, so don't
* assume the string is the same length after calling these functions.
*/
-Unicode Unicode_ToLower(ConstUnicode str, const char *locale);
-Unicode Unicode_ToUpper(ConstUnicode str, const char *locale);
+char *Unicode_ToLower(const char *str, const char *locale);
+char *Unicode_ToUpper(const char *str, const char *locale);
#ifdef HAVE_ICU_38
-Unicode Unicode_ToTitle(ConstUnicode str, const char *locale);
+char *Unicode_ToTitle(const char *str, const char *locale);
#endif
typedef enum {
@@ -89,7 +89,7 @@ typedef enum {
* Normalizes Unicode characters composed of multiple parts into a
* standard form.
*/
-Unicode Unicode_Normalize(ConstUnicode str,
+char *Unicode_Normalize(const char *str,
UnicodeNormalizationForm form);
#ifdef __cplusplus
diff --git a/open-vm-tools/lib/include/unicodeOperations.h b/open-vm-tools/lib/include/unicodeOperations.h
index caca7496..a6966102 100644
--- a/open-vm-tools/lib/include/unicodeOperations.h
+++ b/open-vm-tools/lib/include/unicodeOperations.h
@@ -60,44 +60,44 @@ extern "C" {
* of string".
*/
-int Unicode_CompareRange(ConstUnicode str1,
+int Unicode_CompareRange(const char *str1,
UnicodeIndex str1Start,
UnicodeIndex str1Length,
- ConstUnicode str2,
+ const char *str2,
UnicodeIndex str2Start,
UnicodeIndex str2Length,
Bool ignoreCase);
-UnicodeIndex Unicode_FindSubstrInRange(ConstUnicode str,
+UnicodeIndex Unicode_FindSubstrInRange(const char *str,
UnicodeIndex strStart,
UnicodeIndex strLength,
- ConstUnicode strToFind,
+ const char *strToFind,
UnicodeIndex strToFindStart,
UnicodeIndex strToFindLength);
-UnicodeIndex Unicode_FindLastSubstrInRange(ConstUnicode str,
+UnicodeIndex Unicode_FindLastSubstrInRange(const char *str,
UnicodeIndex strStart,
UnicodeIndex strLength,
- ConstUnicode strToFind,
+ const char *strToFind,
UnicodeIndex strToFindStart,
UnicodeIndex strToFindLength);
-Unicode Unicode_Substr(ConstUnicode str,
- UnicodeIndex start,
- UnicodeIndex length);
+char *Unicode_Substr(const char *str,
+ UnicodeIndex start,
+ UnicodeIndex length);
-Unicode Unicode_ReplaceRange(ConstUnicode destination,
- UnicodeIndex destinationStart,
- UnicodeIndex destinationLength,
- ConstUnicode source,
- UnicodeIndex sourceStart,
- UnicodeIndex sourceLength);
+char *Unicode_ReplaceRange(const char *destination,
+ UnicodeIndex destinationStart,
+ UnicodeIndex destinationLength,
+ const char *source,
+ UnicodeIndex sourceStart,
+ UnicodeIndex sourceLength);
-Unicode Unicode_Join(ConstUnicode first,
- ...);
+char *Unicode_Join(const char *first,
+ ...);
-Unicode Unicode_Format(const char *fmt, ...);
+char *Unicode_Format(const char *fmt, ...);
-UnicodeIndex Unicode_LengthInCodePoints(ConstUnicode str);
+UnicodeIndex Unicode_LengthInCodePoints(const char *str);
/*
* Simple in-line functions that may be used below.
@@ -124,16 +124,12 @@ UnicodeIndex Unicode_LengthInCodePoints(ConstUnicode str);
*/
static INLINE Bool
-Unicode_IsIndexAtCodePointBoundary(ConstUnicode str, // IN:
+Unicode_IsIndexAtCodePointBoundary(const char *str, // IN:
UnicodeIndex index) // IN:
{
ASSERT(index >= 0 && index <= Unicode_LengthInCodeUnits(str));
-#ifdef SUPPORT_UNICODE_OPAQUE
- NOT_IMPLEMENTED();
-#else
return (str[index] & 0xc0) != 0x80;
-#endif
}
@@ -151,7 +147,7 @@ Unicode_IsIndexAtCodePointBoundary(ConstUnicode str, // IN:
* followed by 'source'.
*
* Results:
- * The newly-allocated string. Caller must free with Unicode_Free.
+ * The newly-allocated string. Caller must free with free.
*
* Side effects:
* None
@@ -159,9 +155,9 @@ Unicode_IsIndexAtCodePointBoundary(ConstUnicode str, // IN:
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
-Unicode_Append(ConstUnicode destination, // IN
- ConstUnicode source) // IN
+static INLINE char *
+Unicode_Append(const char *destination, // IN
+ const char *source) // IN
{
return Unicode_ReplaceRange(destination,
-1,
@@ -181,7 +177,7 @@ Unicode_Append(ConstUnicode destination, // IN
* followed by the specified range of 'source'.
*
* Results:
- * The newly-allocated string. Caller must free with Unicode_Free.
+ * The newly-allocated string. Caller must free with free.
*
* Side effects:
* None
@@ -189,9 +185,9 @@ Unicode_Append(ConstUnicode destination, // IN
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
-Unicode_AppendRange(ConstUnicode dest, // IN:
- ConstUnicode src, // IN:
+static INLINE char *
+Unicode_AppendRange(const char *dest, // IN:
+ const char *src, // IN:
UnicodeIndex srcStart, // IN:
UnicodeIndex srcLength) // IN:
{
@@ -226,8 +222,8 @@ Unicode_AppendRange(ConstUnicode dest, // IN:
*/
static INLINE int
-Unicode_Compare(ConstUnicode str1, // IN
- ConstUnicode str2) // IN
+Unicode_Compare(const char *str1, // IN
+ const char *str2) // IN
{
return Unicode_CompareRange(str1,
0,
@@ -261,8 +257,8 @@ Unicode_Compare(ConstUnicode str1, // IN
*/
static INLINE int
-Unicode_CompareIgnoreCase(ConstUnicode str1, // IN
- ConstUnicode str2) // IN
+Unicode_CompareIgnoreCase(const char *str1, // IN
+ const char *str2) // IN
{
return Unicode_CompareRange(str1,
0,
@@ -293,8 +289,8 @@ Unicode_CompareIgnoreCase(ConstUnicode str1, // IN
*/
static INLINE Bool
-UnicodeEndsWith(ConstUnicode str, // IN:
- ConstUnicode suffix, // IN:
+UnicodeEndsWith(const char *str, // IN:
+ const char *suffix, // IN:
Bool ignoreCase) // IN:
{
UnicodeIndex strLength = Unicode_LengthInCodePoints(str);
@@ -316,16 +312,16 @@ UnicodeEndsWith(ConstUnicode str, // IN:
static INLINE Bool
-Unicode_EndsWith(ConstUnicode str, // IN
- ConstUnicode suffix) // IN
+Unicode_EndsWith(const char *str, // IN
+ const char *suffix) // IN
{
return UnicodeEndsWith(str, suffix, FALSE);
}
static INLINE Bool
-Unicode_EndsWithIgnoreCase(ConstUnicode str, // IN
- ConstUnicode suffix) // IN
+Unicode_EndsWithIgnoreCase(const char *str, // IN
+ const char *suffix) // IN
{
return UnicodeEndsWith(str, suffix, TRUE);
}
@@ -351,8 +347,8 @@ Unicode_EndsWithIgnoreCase(ConstUnicode str, // IN
*/
static INLINE UnicodeIndex
-Unicode_Find(ConstUnicode str, // IN
- ConstUnicode strToFind) // IN
+Unicode_Find(const char *str, // IN
+ const char *strToFind) // IN
{
return Unicode_FindSubstrInRange(str,
0,
@@ -384,8 +380,8 @@ Unicode_Find(ConstUnicode str, // IN
*/
static INLINE UnicodeIndex
-Unicode_FindFromIndex(ConstUnicode str, // IN
- ConstUnicode strToFind, // IN
+Unicode_FindFromIndex(const char *str, // IN
+ const char *strToFind, // IN
UnicodeIndex fromIndex) // IN
{
return Unicode_FindSubstrInRange(str,
@@ -418,8 +414,8 @@ Unicode_FindFromIndex(ConstUnicode str, // IN
*/
static INLINE UnicodeIndex
-Unicode_FindInRange(ConstUnicode str, // IN
- ConstUnicode strToFind, // IN
+Unicode_FindInRange(const char *str, // IN
+ const char *strToFind, // IN
UnicodeIndex start, // IN
UnicodeIndex length) // IN
{
@@ -452,8 +448,8 @@ Unicode_FindInRange(ConstUnicode str, // IN
*/
static INLINE UnicodeIndex
-Unicode_FindLast(ConstUnicode str, // IN
- ConstUnicode strToFind) // IN
+Unicode_FindLast(const char *str, // IN
+ const char *strToFind) // IN
{
return Unicode_FindLastSubstrInRange(str,
0,
@@ -485,8 +481,8 @@ Unicode_FindLast(ConstUnicode str, // IN
*/
static INLINE UnicodeIndex
-Unicode_FindLastFromIndex(ConstUnicode str, // IN
- ConstUnicode strToFind, // IN
+Unicode_FindLastFromIndex(const char *str, // IN
+ const char *strToFind, // IN
UnicodeIndex fromIndex) // IN
{
return Unicode_FindLastSubstrInRange(str,
@@ -519,8 +515,8 @@ Unicode_FindLastFromIndex(ConstUnicode str, // IN
*/
static INLINE UnicodeIndex
-Unicode_FindLastInRange(ConstUnicode str, // IN
- ConstUnicode strToFind, // IN
+Unicode_FindLastInRange(const char *str, // IN
+ const char *strToFind, // IN
UnicodeIndex start, // IN
UnicodeIndex length) // IN
{
@@ -542,7 +538,7 @@ Unicode_FindLastInRange(ConstUnicode str, // IN
* string 'source' inserted at the index 'destinationStart'.
*
* Results:
- * The newly-allocated string. Caller must free with Unicode_Free.
+ * The newly-allocated string. Caller must free with free.
*
* Side effects:
* None
@@ -550,10 +546,10 @@ Unicode_FindLastInRange(ConstUnicode str, // IN
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
-Unicode_Insert(ConstUnicode destination, // IN
+static INLINE char *
+Unicode_Insert(const char *destination, // IN
UnicodeIndex destinationStart, // IN
- ConstUnicode source) // IN
+ const char *source) // IN
{
return Unicode_ReplaceRange(destination,
destinationStart,
@@ -574,7 +570,7 @@ Unicode_Insert(ConstUnicode destination, // IN
* 'destinationStart'.
*
* Results:
- * The newly-allocated string. Caller must free with Unicode_Free.
+ * The newly-allocated string. Caller must free with free.
*
* Side effects:
* None
@@ -582,10 +578,10 @@ Unicode_Insert(ConstUnicode destination, // IN
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
-Unicode_InsertRange(ConstUnicode destination,
+static INLINE char *
+Unicode_InsertRange(const char *destination,
UnicodeIndex destinationStart,
- ConstUnicode source,
+ const char *source,
UnicodeIndex sourceStart,
UnicodeIndex sourceLength)
{
@@ -615,8 +611,8 @@ Unicode_InsertRange(ConstUnicode destination,
*/
static INLINE Bool
-Unicode_IsEqual(ConstUnicode str1, // IN
- ConstUnicode str2) // IN
+Unicode_IsEqual(const char *str1, // IN
+ const char *str2) // IN
{
return Unicode_CompareRange(str1,
0,
@@ -638,7 +634,7 @@ Unicode_IsEqual(ConstUnicode str1, // IN
* removed.
*
* Results:
- * The newly-allocated string. Caller must free with Unicode_Free.
+ * The newly-allocated string. Caller must free with free.
*
* Side effects:
* None
@@ -646,8 +642,8 @@ Unicode_IsEqual(ConstUnicode str1, // IN
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
-Unicode_RemoveRange(ConstUnicode destination,
+static INLINE char *
+Unicode_RemoveRange(const char *destination,
UnicodeIndex start,
UnicodeIndex length)
{
@@ -666,7 +662,7 @@ Unicode_RemoveRange(ConstUnicode destination,
* with 'source'.
*
* Results:
- * The newly-allocated string. Caller must free with Unicode_Free.
+ * The newly-allocated string. Caller must free with free.
*
* Side effects:
* None
@@ -674,11 +670,11 @@ Unicode_RemoveRange(ConstUnicode destination,
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
-Unicode_Replace(ConstUnicode destination,
+static INLINE char *
+Unicode_Replace(const char *destination,
UnicodeIndex destinationStart,
UnicodeIndex destinationLength,
- ConstUnicode source)
+ const char *source)
{
return Unicode_ReplaceRange(destination,
destinationStart,
@@ -708,9 +704,9 @@ Unicode_Replace(ConstUnicode destination,
*/
static INLINE Bool
-UnicodeStartsWith(ConstUnicode str, // IN:
- ConstUnicode prefix, // IN:
- Bool ignoreCase) // IN:
+UnicodeStartsWith(const char *str, // IN:
+ const char *prefix, // IN:
+ Bool ignoreCase) // IN:
{
UnicodeIndex strLength = Unicode_LengthInCodePoints(str);
UnicodeIndex prefixLength = Unicode_LengthInCodePoints(prefix);
@@ -730,16 +726,16 @@ UnicodeStartsWith(ConstUnicode str, // IN:
static INLINE Bool
-Unicode_StartsWith(ConstUnicode str, // IN
- ConstUnicode prefix) // IN
+Unicode_StartsWith(const char *str, // IN
+ const char *prefix) // IN
{
return UnicodeStartsWith(str, prefix, FALSE);
}
static INLINE Bool
-Unicode_StartsWithIgnoreCase(ConstUnicode str, // IN
- ConstUnicode prefix) // IN
+Unicode_StartsWithIgnoreCase(const char *str, // IN
+ const char *prefix) // IN
{
return UnicodeStartsWith(str, prefix, TRUE);
}
@@ -755,7 +751,7 @@ Unicode_StartsWithIgnoreCase(ConstUnicode str, // IN
*
* Results:
* The newly-allocated truncated copy of 'str'. Caller must free
- * with Unicode_Free.
+ * with free.
*
* Side effects:
* None
@@ -763,8 +759,8 @@ Unicode_StartsWithIgnoreCase(ConstUnicode str, // IN
*-----------------------------------------------------------------------------
*/
-static INLINE Unicode
-Unicode_Truncate(ConstUnicode str, // IN
+static INLINE char *
+Unicode_Truncate(const char *str, // IN
UnicodeIndex length) // IN
{
return Unicode_Substr(str, 0, length);
diff --git a/open-vm-tools/lib/include/unicodeTransforms.h b/open-vm-tools/lib/include/unicodeTransforms.h
index 8e72faf2..b7d2a409 100644
--- a/open-vm-tools/lib/include/unicodeTransforms.h
+++ b/open-vm-tools/lib/include/unicodeTransforms.h
@@ -44,14 +44,14 @@ extern "C" {
* Standardizes the case of the string by doing a locale-agnostic
* uppercase operation, then a locale-agnostic lowercase operation.
*/
-Unicode Unicode_FoldCase(ConstUnicode str);
+char *Unicode_FoldCase(const char *str);
/*
* Trims whitespace from either side of the string.
*/
-Unicode Unicode_Trim(ConstUnicode str);
-Unicode Unicode_TrimLeft(ConstUnicode str);
-Unicode Unicode_TrimRight(ConstUnicode str);
+char *Unicode_Trim(const char *str);
+char *Unicode_TrimLeft(const char *str);
+char *Unicode_TrimRight(const char *str);
#ifdef __cplusplus
}
diff --git a/open-vm-tools/lib/include/unicodeTypes.h b/open-vm-tools/lib/include/unicodeTypes.h
index b6b52cda..ca2b6906 100644
--- a/open-vm-tools/lib/include/unicodeTypes.h
+++ b/open-vm-tools/lib/include/unicodeTypes.h
@@ -39,31 +39,6 @@ extern "C" {
#include "vm_basic_types.h"
#include "vm_assert.h"
-#if defined(SUPPORT_UNICODE_OPAQUE)
-
-/*
- * To assist with finding code that hasn't been internationalized, we
- * support building with an opaque Unicode type. This catches users
- * passing a char * of unknown encoding to Unicode functions, and
- * assigning a Unicode to a char *.
- */
-
-typedef struct UnicodeImpl UnicodeImpl;
-typedef UnicodeImpl * Unicode;
-typedef const UnicodeImpl * ConstUnicode;
-
-#else
-
-/*
- * As a transitionary development tactic to prevent code churn while the
- * Unicode libraries are being developed, we'll start with a simple
- * implementation of Unicode as UTF-8 char *.
- */
-typedef char * Unicode;
-typedef const char * ConstUnicode;
-
-#endif
-
typedef ssize_t UnicodeIndex;
/*
diff --git a/open-vm-tools/lib/include/userlock.h b/open-vm-tools/lib/include/userlock.h
index 4863a6c4..70e93978 100644
--- a/open-vm-tools/lib/include/userlock.h
+++ b/open-vm-tools/lib/include/userlock.h
@@ -38,6 +38,7 @@ typedef struct MXUserRWLock MXUserRWLock;
typedef struct MXUserRankLock MXUserRankLock;
typedef struct MXUserCondVar MXUserCondVar;
typedef struct MXUserSemaphore MXUserSemaphore;
+typedef struct MXUserEvent MXUserEvent;
typedef struct MXUserBarrier MXUserBarrier;
/*
@@ -47,9 +48,6 @@ typedef struct MXUserBarrier MXUserBarrier;
MXUserExclLock *MXUser_CreateExclLock(const char *name,
MX_Rank rank);
-MXUserExclLock *MXUser_CreateExclLockSilent(const char *name,
- MX_Rank rank);
-
void MXUser_AcquireExclLock(MXUserExclLock *lock);
Bool MXUser_TryAcquireExclLock(MXUserExclLock *lock);
void MXUser_ReleaseExclLock(MXUserExclLock *lock);
@@ -60,10 +58,6 @@ MXUserExclLock *MXUser_CreateSingletonExclLock(Atomic_Ptr *lockStorage,
const char *name,
MX_Rank rank);
-Bool MXUser_ControlExclLock(MXUserExclLock *lock,
- uint32 command,
- ...);
-
MXUserCondVar *MXUser_CreateCondVarExclLock(MXUserExclLock *lock);
void MXUser_WaitCondVarExclLock(MXUserExclLock *lock,
@@ -73,6 +67,20 @@ void MXUser_TimedWaitCondVarExclLock(MXUserExclLock *lock,
MXUserCondVar *condVar,
uint32 msecWait);
+Bool MXUser_EnableStatsExclLock(MXUserExclLock *lock,
+ Bool trackAcquisitionTime,
+ Bool trackHeldTime);
+
+Bool MXUser_DisableStatsExclLock(MXUserExclLock *lock);
+
+Bool MXUser_SetContentionRatioFloorExclLock(MXUserExclLock *lock,
+ double ratio);
+
+Bool MXUser_SetContentionCountFloorExclLock(MXUserExclLock *lock,
+ uint64 count);
+
+Bool MXUser_SetContentionDurationFloorExclLock(MXUserExclLock *lock,
+ uint64 count);
/*
* Recursive lock.
@@ -81,9 +89,6 @@ void MXUser_TimedWaitCondVarExclLock(MXUserExclLock *lock,
MXUserRecLock *MXUser_CreateRecLock(const char *name,
MX_Rank rank);
-MXUserRecLock *MXUser_CreateRecLockSilent(const char *name,
- MX_Rank rank);
-
void MXUser_AcquireRecLock(MXUserRecLock *lock);
Bool MXUser_TryAcquireRecLock(MXUserRecLock *lock);
void MXUser_ReleaseRecLock(MXUserRecLock *lock);
@@ -94,10 +99,6 @@ MXUserRecLock *MXUser_CreateSingletonRecLock(Atomic_Ptr *lockStorage,
const char *name,
MX_Rank rank);
-Bool MXUser_ControlRecLock(MXUserRecLock *lock,
- uint32 command,
- ...);
-
void MXUser_DumpRecLock(MXUserRecLock *lock);
MXUserCondVar *MXUser_CreateCondVarRecLock(MXUserRecLock *lock);
@@ -113,6 +114,22 @@ void MXUser_IncRefRecLock(MXUserRecLock *lock);
void MXUser_DecRefRecLock(MXUserRecLock *lock);
+Bool MXUser_EnableStatsRecLock(MXUserRecLock *lock,
+ Bool trackAcquisitionTime,
+ Bool trackHeldTime);
+
+Bool MXUser_DisableStatsRecLock(MXUserRecLock *lock);
+
+Bool MXUser_SetContentionRatioFloorRecLock(MXUserRecLock *lock,
+ double ratio);
+
+Bool MXUser_SetContentionCountFloorRecLock(MXUserRecLock *lock,
+ uint64 count);
+
+Bool MXUser_SetContentionDurationFloorRecLock(MXUserRecLock *lock,
+ uint64 count);
+
+
/*
* Read-write lock
*/
@@ -136,9 +153,22 @@ MXUserRWLock *MXUser_CreateSingletonRWLock(Atomic_Ptr *lockStorage,
const char *name,
MX_Rank rank);
-Bool MXUser_ControlRWLock(MXUserRWLock *lock,
- uint32 command,
- ...);
+/*
+ * Stateful auto-reset event
+ */
+
+MXUserEvent *MXUser_CreateEvent(const char *name,
+ MX_Rank rank);
+
+void MXUser_SignalEvent(MXUserEvent *event);
+void MXUser_WaitEvent(MXUserEvent *event);
+Bool MXUser_TryWaitEvent(MXUserEvent *event);
+MXSemaHandle MXUser_GetHandleForEvent(MXUserEvent *event);
+void MXUser_DestroyEvent(MXUserEvent *event);
+
+MXUserEvent *MXUser_CreateSingletonEvent(Atomic_Ptr *eventStorage,
+ const char *name,
+ MX_Rank rank);
/*
* Computational barrier
@@ -163,9 +193,6 @@ MXUserBarrier *MXUser_CreateSingletonBarrier(Atomic_Ptr *barrierStorage,
MXUserSemaphore *MXUser_CreateSemaphore(const char *name,
MX_Rank rank);
-MXUserSemaphore *MXUser_CreateSemaphoreSolent(const char *name,
- MX_Rank rank);
-
void MXUser_DestroySemaphore(MXUserSemaphore *sema);
void MXUser_UpSemaphore(MXUserSemaphore *sema);
void MXUser_DownSemaphore(MXUserSemaphore *sema);
@@ -203,25 +230,13 @@ void MXUser_SignalCondVar(MXUserCondVar *condVar);
void MXUser_BroadcastCondVar(MXUserCondVar *condVar);
void MXUser_DestroyCondVar(MXUserCondVar *condVar);
-/*
- * MXUser_Control[Excl, Rec, RW] commands
- */
+void MXUser_LockingTreeCollection(Bool enabled);
+Bool MXUser_IsLockingTreeAvailable(void);
+void MXUser_DumpLockTree(const char *fileName,
+ const char *timeStamp);
-#define MXUSER_CONTROL_ACQUISITION_HISTO 0 // minValue, decades
-#define MXUSER_CONTROL_HELD_HISTO 1 // minValue, decades
-#define MXUSER_CONTROL_ENABLE_STATS 2 // no arguments
+void MXUser_EmptyLockTree(void);
-#define MXUSER_DEFAULT_HISTO_MIN_VALUE_NS 1000 // 1 usec
-#define MXUSER_DEFAULT_HISTO_DECADES 7 // 1 usec to 10 seconds
-
-struct MX_MutexRec;
-
-#if defined(VMX86_VMX)
-MXUserRecLock *MXUser_InitFromMXRec(const char *name,
- struct MX_MutexRec *mutex,
- MX_Rank rank,
- Bool isBelowBull);
-#endif
#if defined(VMX86_DEBUG) && !defined(DISABLE_MXUSER_DEBUG)
#define MXUSER_DEBUG // debugging "everywhere" when requested
@@ -231,7 +246,6 @@ MXUserRecLock *MXUser_InitFromMXRec(const char *name,
void MXUser_TryAcquireFailureControl(Bool (*func)(const char *lockName));
Bool MXUser_IsCurThreadHoldingLocks(void);
#endif
-
void MXUser_StatisticsControl(double contentionRatioFloor,
uint64 minAccessCountFloor,
uint64 contentionDurationFloor);
@@ -247,8 +261,11 @@ void MXUser_SetStatsFunc(void *context,
void MXUser_SetInPanic(void);
Bool MXUser_InPanic(void);
+struct MX_MutexRec;
+
MXUserRecLock *MXUser_BindMXMutexRec(struct MX_MutexRec *mutex,
MX_Rank rank);
+
struct MX_MutexRec *MXUser_GetRecLockVmm(MXUserRecLock *lock);
MX_Rank MXUser_GetRecLockRank(MXUserRecLock *lock);
#endif // _USERLOCK_H_
diff --git a/open-vm-tools/lib/include/util.h b/open-vm-tools/lib/include/util.h
index 8d1c027b..2e1d4dee 100644
--- a/open-vm-tools/lib/include/util.h
+++ b/open-vm-tools/lib/include/util.h
@@ -42,6 +42,7 @@
#include <windows.h> /* for definition of HANDLE */
#endif
#else
+ #include <unistd.h>
#include <sys/types.h>
#include "errno.h"
#endif
@@ -55,14 +56,19 @@
*/
#if defined(_WIN32)
typedef DWORD Util_ThreadID;
+#elif defined(__linux__) || defined(__ANDROID__)
+ typedef pid_t Util_ThreadID;
+#elif defined(__APPLE__)
+# include <pthread.h>
+ typedef mach_port_t Util_ThreadID;
+#elif defined(__sun__)
+# include <thread.h>
+ typedef thread_t Util_ThreadID;
+#elif defined(__FreeBSD__)
+# include <pthread.h>
+ typedef pthread_t Util_ThreadID;
#else
- #include <unistd.h>
- #if defined(__APPLE__) || defined(__FreeBSD__)
- #include <pthread.h>
- typedef pthread_t Util_ThreadID;
- #else // Linux et al
- typedef pid_t Util_ThreadID;
- #endif
+# error "Need typedef for Util_ThreadID"
#endif
uint32 CRC_Compute(const uint8 *buf, int len);
@@ -70,7 +76,7 @@ uint32 Util_Checksum32(const uint32 *buf, int len);
uint32 Util_Checksum(const uint8 *buf, int len);
uint32 Util_Checksumv(void *iov, int numEntries);
uint32 Util_HashString(const char *str);
-Unicode Util_ExpandString(ConstUnicode fileName);
+char *Util_ExpandString(const char *fileName);
void Util_ExitThread(int);
NORETURN void Util_ExitProcessAbruptly(int);
int Util_HasAdminPriv(void);
@@ -145,14 +151,15 @@ int Util_CompareDotted(const char *s1, const char *s2);
* This enum defines how Util_GetOpt should handle non-option arguments:
*
* UTIL_NONOPT_PERMUTE: Permute argv so that all non-options are at the end.
- * UTIL_NONOPT_STOP: Stop when first non-option argument is seen.
+ * UTIL_NONOPT_STOP: Stop when first non-option argument is seen. (This is
+ * the standard POSIX behavior.)
* UTIL_NONOPT_ALL: Return each non-option argument as if it were
* an option with character code 1.
*/
typedef enum { UTIL_NONOPT_PERMUTE, UTIL_NONOPT_STOP, UTIL_NONOPT_ALL } Util_NonOptMode;
struct option;
int Util_GetOpt(int argc, char * const *argv, const struct option *opts,
- Util_NonOptMode mode);
+ Util_NonOptMode mode, Bool manualErrorHandling);
#if defined(VMX86_STATS)
@@ -167,7 +174,7 @@ Bool Util_QueryCStResidency(uint32 *numCpus, uint32 *numCStates,
#define UTIL_FASTRAND_SEED_MAX (0x7fffffff)
Bool Util_Throttle(uint32 count);
uint32 Util_FastRand(uint32 seed);
-
+uint64 Util_CheckSum64(uint32 *data, unsigned numWords);
// Not thread safe!
void Util_OverrideHomeDir(const char *path);
@@ -480,7 +487,7 @@ Util_Zero(void *buf, // OUT
*/
static INLINE void
-Util_ZeroString(char *str) // IN/OUT
+Util_ZeroString(char *str) // IN/OUT/OPT
{
if (str != NULL) {
Util_Zero(str, strlen(str));
@@ -507,7 +514,7 @@ Util_ZeroString(char *str) // IN/OUT
*/
static INLINE void
-Util_ZeroFree(void *buf, // OUT
+Util_ZeroFree(void *buf, // OUT/OPT
size_t bufSize) // IN
{
if (buf != NULL) {
@@ -535,7 +542,7 @@ Util_ZeroFree(void *buf, // OUT
*/
static INLINE void
-Util_ZeroFreeString(char *str) // IN
+Util_ZeroFreeString(char *str) // IN/OUT/OPT
{
if (str != NULL) {
Util_ZeroString(str);
@@ -563,7 +570,7 @@ Util_ZeroFreeString(char *str) // IN
*/
static INLINE void
-Util_ZeroFreeStringW(wchar_t *str) // IN
+Util_ZeroFreeStringW(wchar_t *str) // IN/OUT/OPT
{
if (str != NULL) {
Util_Zero(str, wcslen(str) * sizeof *str);
@@ -597,7 +604,7 @@ Util_ZeroFreeStringW(wchar_t *str) // IN
*/
static INLINE void
-Util_FreeList(void **list, // IN/OUT: the list to free
+Util_FreeList(void **list, // IN/OUT/OPT: the list to free
ssize_t length) // IN: the length
{
if (list == NULL) {
@@ -624,37 +631,13 @@ Util_FreeList(void **list, // IN/OUT: the list to free
}
static INLINE void
-Util_FreeStringList(char **list, // IN/OUT: the list to free
+Util_FreeStringList(char **list, // IN/OUT/OPT: the list to free
ssize_t length) // IN: the length
{
Util_FreeList((void **) list, length);
}
#endif
-#ifndef _WIN32
-/*
- *-----------------------------------------------------------------------------
- *
- * Util_IsFileDescriptorOpen --
- *
- * Check if given file descriptor is open.
- *
- * Results:
- * TRUE if fd is open.
- *
- * Side effects:
- * Clobbers errno.
- *
- *-----------------------------------------------------------------------------
- */
-
-static INLINE Bool
-Util_IsFileDescriptorOpen(int fd) // IN
-{
- return (lseek(fd, 0L, SEEK_CUR) == -1) ? errno != EBADF : TRUE;
-}
-#endif /* !_WIN32 */
-
/*
*-----------------------------------------------------------------------------
@@ -675,7 +658,9 @@ Util_IsFileDescriptorOpen(int fd) // IN
*/
static INLINE void *
-Util_Memcpy32(void *dst, const void *src, size_t nbytes)
+Util_Memcpy32(void *dst,
+ const void *src,
+ size_t nbytes)
{
ASSERT((nbytes % 4) == 0);
#if defined __GNUC__ && (defined(__i386__) || defined(__x86_64__))
diff --git a/open-vm-tools/lib/include/util_shared.h b/open-vm-tools/lib/include/util_shared.h
index 46c5c131..a061f119 100644
--- a/open-vm-tools/lib/include/util_shared.h
+++ b/open-vm-tools/lib/include/util_shared.h
@@ -94,6 +94,38 @@ Util_FastRand(uint32 seed)
}
+/*
+ *----------------------------------------------------------------------
+ * Util_Checksum64 --
+ * 64-bit implementation of Fletcher's checksum. Fast and simple.
+ * Guarantees a non-zero checksum (so 0 can mean "uninitialized").
+ * One known weakness is that the 32-bit value of 0 is
+ * indistinguishable from ~0. The magic number 92680 was computed
+ * to be the most iterations before sum2 could overflow 64 bits.
+ *----------------------------------------------------------------------
+ */
+uint64
+Util_CheckSum64(uint32 *data, unsigned numWords)
+{
+ uint64 sum1 = 0xffffffff, sum2 = 0xffffffff;
+
+ while (numWords > 0) {
+ unsigned tlen = numWords > 92680 ? 92680 : numWords;
+ numWords -= tlen;
+ do {
+ sum1 += *data++;
+ sum2 += sum1;
+ } while (--tlen > 0);
+ sum1 = (sum1 & 0xffffffff) + (sum1 >> 32);
+ sum2 = (sum2 & 0xffffffff) + (sum2 >> 32);
+ }
+ /* Second reduction step to reduce sums to 32 bits */
+ sum1 = (sum1 & 0xffffffff) + (sum1 >> 32);
+ sum2 = (sum2 & 0xffffffff) + (sum2 >> 32);
+ return (sum2 << 32) | sum1;
+}
+
+
#if defined(USERLEVEL) || defined(VMX86_DEBUG)
static uint32 crcTable[256];
diff --git a/open-vm-tools/lib/include/uuid.h b/open-vm-tools/lib/include/uuid.h
index 6fe79fd8..cad5de3e 100644
--- a/open-vm-tools/lib/include/uuid.h
+++ b/open-vm-tools/lib/include/uuid.h
@@ -25,6 +25,10 @@
#ifndef _UUID_H_
#define _UUID_H_
+#ifdef __cplusplus
+extern "C"{
+#endif
+
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
@@ -41,9 +45,7 @@ typedef enum {
UUID_UNKNOWN
} UUIDStyle;
-Bool UUID_ConvertToBin(uint8 dest_id[UUID_SIZE], const char *text);
-char *UUID_ConvertToText(const uint8 id[UUID_SIZE]);
-
+/* Scheme control */
#define UUID_CREATE_WS4 0 /* the "original", WS4 and earlier scheme */
#define UUID_CREATE_WS5 1 /* the WS5 scheme */
#define UUID_CREATE_WS6 2 /* the WS6 scheme - "native" path */
@@ -53,11 +55,93 @@ char *UUID_ConvertToText(const uint8 id[UUID_SIZE]);
#define UUID_CREATE_WS65 4 /* the WS65 scheme - UTF-8 path */
#define UUID_CREATE_CURRENT 4 /* the current scheme - always the latest */
-char *UUID_Create(const char *configFileFullPath, int schemeControl);
+/*
+ * An RFC 4122-compliant UUID.
+ *
+ * See RFC 4122 section 4.1.2 (Layout and Byte Order). All multi-byte types are
+ * stored in big-endian (most significant byte first) order.
+ *
+ * The UUID packed text string
+ * 00112233-4455-6677-8899-AABBCCDDEEFF
+ * represents
+ * timeLow = 0x00112233
+ * timeMid = 0x4455
+ * timeHiAndVersion = 0x6677
+ * clockSeqHiAndReserved = 0x88
+ * clockSeqLow = 0x99
+ * node[0] = 0xAA
+ * node[1] = 0xBB
+ * node[2] = 0xCC
+ * node[3] = 0xDD
+ * node[4] = 0xEE
+ * node[5] = 0xFF
+ * and the structure is stored as the sequence of bytes
+ * 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
+ */
+
+typedef
+#include "vmware_pack_begin.h"
+struct {
+ uint32 timeLow;
+ uint16 timeMid;
+ uint16 timeHiAndVersion;
+ uint8 clockSeqHiAndReserved;
+ uint8 clockSeqLow;
+ uint8 node[6];
+}
+#include "vmware_pack_end.h"
+UUIDRFC4122;
+
+
+/*
+ * An EFI/UEFI/Microsoft-compliant GUID.
+ *
+ * See MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c::StrToGuid(),
+ * BaseTools/Source/C/Common/ParseInf.c::StringToGuid(),
+ * http://en.wikipedia.org/wiki/GUID . All multi-byte types are stored in CPU
+ * (a.k.a. native) byte order.
+ *
+ * The GUID packed text string
+ * 00112233-4455-6677-8899-AABBCCDDEEFF
+ * represents
+ * data1 = 0x00112233
+ * data2 = 0x4455
+ * data3 = 0x6677
+ * data4[0] = 0x88
+ * data4[1] = 0x99
+ * data4[2] = 0xAA
+ * data4[3] = 0xBB
+ * data4[4] = 0xCC
+ * data4[5] = 0xDD
+ * data4[6] = 0xEE
+ * data4[7] = 0xFF
+ * and the structure is stored as the sequence of bytes
+ * big-endian CPU: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
+ * little-endian CPU: 33 22 11 00 55 44 77 66 88 99 AA BB CC DD EE FF
+ */
+
+typedef
+#include "vmware_pack_begin.h"
+struct {
+ uint32 data1;
+ uint16 data2;
+ uint16 data3;
+ uint8 data4[8];
+}
+#include "vmware_pack_end.h"
+EFIGUID;
+
+
+Bool UUID_ConvertToBin(uint8 dest_id[UUID_SIZE], const char *text);
+char *UUID_ConvertToText(const uint8 id[UUID_SIZE]);
+
+char *UUID_Create(const char *configFileFullPath, int schemeControl);
char *UUID_CreateRandom(void);
-char *UUID_CreateRandomRFC4122V4(void);
+void UUID_CreateRandomRFC4122V4(UUIDRFC4122 *id);
+void UUID_CreateRandomEFI(EFIGUID *id);
char *UUID_CreateRandomVpxStyle(uint8 vpxdId, UUIDStyle);
+
Bool UUID_IsUUIDGeneratedByThatVpxd(const uint8 *id, int vpxdInstanceId);
char *UUID_PackText(const char *text, char *pack, int packLen);
char *UUID_ProperHostUUID(void);
@@ -65,4 +149,9 @@ char *UUID_GetHostUUID(void);
UUIDStyle UUID_GetStyle(const uint8 *id);
/* like UUID_GetHostUUID, except gets actual host UUID */
char *UUID_GetRealHostUUID(void);
+
+#ifdef __cplusplus
+} // extern "C" {
+#endif
+
#endif
diff --git a/open-vm-tools/lib/include/vix.h b/open-vm-tools/lib/include/vix.h
index 0d971d65..ffcf5d42 100644
--- a/open-vm-tools/lib/include/vix.h
+++ b/open-vm-tools/lib/include/vix.h
@@ -220,7 +220,7 @@ enum {
VIX_E_SNAPSHOT_MAXSNAPSHOTS = 13019,
VIX_E_SNAPSHOT_MIN_FREE_SPACE = 13020,
VIX_E_SNAPSHOT_HIERARCHY_TOODEEP = 13021,
- VIX_E_SNAPSHOT_RRSUSPEND = 13022,
+ // DEPRECRATED VIX_E_SNAPSHOT_RRSUSPEND = 13022,
VIX_E_SNAPSHOT_NOT_REVERTABLE = 13024,
/* Host Errors */
@@ -318,7 +318,7 @@ enum {
VIX_E_TOOLS_INSTALL_INIT_FAILED = 21005,
VIX_E_TOOLS_INSTALL_AUTO_NOT_SUPPORTED = 21006,
VIX_E_TOOLS_INSTALL_GUEST_NOT_READY = 21007,
- VIX_E_TOOLS_INSTALL_SIG_CHECK_FAILED = 21008,
+ /* VIX_E_TOOLS_INSTALL_SIG_CHECK_FAILED = 21008, Removed in version 1.15.0 */
VIX_E_TOOLS_INSTALL_ERROR = 21009,
VIX_E_TOOLS_INSTALL_ALREADY_UP_TO_DATE = 21010,
VIX_E_TOOLS_INSTALL_IN_PROGRESS = 21011,
@@ -817,39 +817,6 @@ enum {
//#define VIX_ADMINISTRATOR_USER_NAME "__VMware_Vix_Guest_User_Admin__"
//#define VIX_CONSOLE_USER_NAME "__VMware_Vix_Guest_Console_User__"
-
-/*
- * Following functions were removed in version 1.11.
- *
- VixHandle VixVM_BeginRecording(VixHandle vmHandle,
- const char *displayName,
- const char *description,
- int options,
- VixHandle propertyList,
- VixEventProc *callbackProc,
- void *clientData);
-
- VixHandle VixVM_EndRecording(VixHandle vmHandle,
- int options,
- VixHandle propertyList,
- VixEventProc *callbackProc,
- void *clientData);
-
- VixHandle VixVM_BeginReplay(VixHandle vmHandle,
- VixHandle snapshotHandle,
- int options,
- VixHandle propertyList,
- VixEventProc *callbackProc,
- void *clientData);
-
- VixHandle VixVM_EndReplay(VixHandle vmHandle,
- int options,
- VixHandle propertyList,
- VixEventProc *callbackProc,
- void *clientData);
-
- */
-
/*
* Guest operations
*/
diff --git a/open-vm-tools/lib/include/vixCommands.h b/open-vm-tools/lib/include/vixCommands.h
index 2f7719a3..5be7a121 100644
--- a/open-vm-tools/lib/include/vixCommands.h
+++ b/open-vm-tools/lib/include/vixCommands.h
@@ -1122,24 +1122,13 @@ VixMsgRemoveBulkSnapshotRequest;
*/
typedef
#include "vmware_pack_begin.h"
-struct VixMsgVMSnapshotLoggingRequest {
+struct VixMsgVMSnapshotPauseRequest {
VixCommandRequestHeader header;
int32 options;
}
#include "vmware_pack_end.h"
-VixMsgVMSnapshotLoggingRequest;
-
-typedef
-#include "vmware_pack_begin.h"
-struct VixMsgRecordReplayEvent {
- VixMsgEventHeader eventHeader;
-
- int32 newRecordState;
- int32 reason;
-}
-#include "vmware_pack_end.h"
-VixMsgRecordReplayEvent;
+VixMsgVMSnapshotPauseRequest;
typedef
#include "vmware_pack_begin.h"
@@ -1455,46 +1444,6 @@ struct VixMsgConnectDeviceRequest {
}
#include "vmware_pack_end.h"
VixMsgConnectDeviceRequest;
-/*
- * **********************************************************
- * Get the list of VProbes exported by a given VM. The request is
- * parameterless, and so generic.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct VixMsgGetVProbesResponse {
- VixCommandResponseHeader header;
- int32 numEntries;
-}
-#include "vmware_pack_end.h"
-VixMsgGetVProbesResponse;
-
-/*
- * **********************************************************
- * Load a vprobe script into a given VM. The request is a string
- * to be loaded. The response is a collection of warning and error
- * strings; zero errors indicates success.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct VixMsgVProbeLoadRequest {
- VixCommandRequestHeader header;
- char string[1]; /* variable length */
-}
-#include "vmware_pack_end.h"
-VixMsgVProbeLoadRequest;
-
-typedef
-#include "vmware_pack_begin.h"
-struct VixMsgVProbeLoadResponse {
- VixCommandResponseHeader header;
- uint32 numWarnings;
- uint32 numErrors;
- uint32 instanceID;
- char warningsAndErrors[1]; /* variable length */
-}
-#include "vmware_pack_end.h"
-VixMsgVProbeLoadResponse;
/*
* **********************************************************
@@ -2265,19 +2214,19 @@ enum {
VIX_COMMAND_MOUNT_HGFS_FOLDERS = 101,
VIX_COMMAND_HOT_EXTEND_DISK = 102,
- VIX_COMMAND_GET_VPROBES_VERSION = 104,
- VIX_COMMAND_GET_VPROBES = 105,
- VIX_COMMAND_VPROBE_GET_GLOBALS = 106,
- VIX_COMMAND_VPROBE_LOAD = 107,
- VIX_COMMAND_VPROBE_RESET = 108,
+ /* DEPRECATED VIX_COMMAND_GET_VPROBES_VERSION = 104, */
+ /* DEPRECATED VIX_COMMAND_GET_VPROBES = 105, */
+ /* DEPRECATED VIX_COMMAND_VPROBE_GET_GLOBALS = 106, */
+ /* DEPRECATED VIX_COMMAND_VPROBE_LOAD = 107, */
+ /* DEPRECATED VIX_COMMAND_VPROBE_RESET = 108, */
/* DEPRECATED VIX_COMMAND_LIST_USB_DEVICES = 109, */
VIX_COMMAND_CONNECT_HOST = 110,
VIX_COMMAND_CREATE_LINKED_CLONE = 112,
- VIX_COMMAND_STOP_SNAPSHOT_LOG_RECORDING = 113,
- VIX_COMMAND_STOP_SNAPSHOT_LOG_PLAYBACK = 114,
+ /* DEPRECATED VIX_COMMAND_STOP_SNAPSHOT_LOG_RECORDING = 113, */
+ /* DEPRECATED VIX_COMMAND_STOP_SNAPSHOT_LOG_PLAYBACK = 114, */
VIX_COMMAND_SAMPLE_COMMAND = 115,
@@ -2316,16 +2265,16 @@ enum {
VIX_COMMAND_HOT_ADD_DEVICE = 138,
VIX_COMMAND_HOT_REMOVE_DEVICE = 139,
- VIX_COMMAND_DEBUGGER_ATTACH = 140,
- VIX_COMMAND_DEBUGGER_DETACH = 141,
- VIX_COMMAND_DEBUGGER_SEND_COMMAND = 142,
+ /* DEPRECATED VIX_COMMAND_DEBUGGER_ATTACH = 140, */
+ /* DEPRECATED VIX_COMMAND_DEBUGGER_DETACH = 141, */
+ /* DEPRECATED VIX_COMMAND_DEBUGGER_SEND_COMMAND = 142, */
/* DEPRECATED VIX_COMMAND_GET_RECORD_STATE = 143, */
/* DEPRECATED VIX_COMMAND_SET_RECORD_STATE = 144, */
- /* DEPRECATEDVIX_COMMAND_REMOVE_RECORD_STATE = 145, */
- /* VIX_COMMAND_GET_REPLAY_STATE = 146, */
- /* VIX_COMMAND_SET_REPLAY_STATE = 147, */
- /* VIX_COMMAND_REMOVE_REPLAY_STATE = 148, */
+ /* DEPRECATED VIX_COMMAND_REMOVE_RECORD_STATE = 145, */
+ /* DEPRECATED VIX_COMMAND_GET_REPLAY_STATE = 146, */
+ /* DEPRECATED VIX_COMMAND_SET_REPLAY_STATE = 147, */
+ /* DEPRECATED VIX_COMMAND_REMOVE_REPLAY_STATE = 148, */
/* DEPRECATED VIX_COMMAND_CANCEL_USER_PROGRESS_MESSAGE = 150, */
diff --git a/open-vm-tools/lib/include/vm_assert.h b/open-vm-tools/lib/include/vm_assert.h
index f36f1bef..6223b287 100644
--- a/open-vm-tools/lib/include/vm_assert.h
+++ b/open-vm-tools/lib/include/vm_assert.h
@@ -103,10 +103,8 @@ extern "C" {
#if !defined VMM || defined MONITOR_APP // {
-#if defined VMKPANIC
-
+#if defined (VMKPANIC)
#include "vmk_assert.h"
-
#else /* !VMKPANIC */
#define _ASSERT_PANIC(name) \
Panic(_##name##Fmt "\n", __FILE__, __LINE__)
@@ -335,12 +333,19 @@ void WarningThrottled(uint32 *count, const char *fmt, ...) PRINTF_DECL(2, 3);
* generate a warning.
*/
+#if defined(_Static_assert) || defined(__cplusplus) || \
+ !defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
#define ASSERT_ON_COMPILE(e) \
do { \
enum { AssertOnCompileMisused = ((e) ? 1 : -1) }; \
UNUSED_TYPE(typedef char AssertOnCompileFailed[AssertOnCompileMisused]); \
} while (0)
-
+#else
+#define ASSERT_ON_COMPILE(e) \
+ do { \
+ _Static_assert(e, #e); \
+ } while (0);
+#endif
/*
* To put an ASSERT_ON_COMPILE() outside a function, wrap it
diff --git a/open-vm-tools/lib/include/vm_atomic.h b/open-vm-tools/lib/include/vm_atomic.h
index f94d8157..187a0d14 100644
--- a/open-vm-tools/lib/include/vm_atomic.h
+++ b/open-vm-tools/lib/include/vm_atomic.h
@@ -22,16 +22,10 @@
* Atomic power
*
* Note: Only partially tested on ARM processors: Works for View Open
- * Client, which shouldn't have threads.
+ * Client, which shouldn't have threads, and ARMv8 processors.
*
* In ARM, GCC intrinsics (__sync*) compile but might not
- * work, while MS intrinsics (_Interlocked*) do not compile,
- * and ARM has no equivalent to the "lock" instruction prior to
- * ARMv6; the current ARM target is ARMv5. According to glibc
- * documentation, ARMv5 cannot have atomic code in user space.
- * Instead a Linux system call to kernel code referenced in
- * entry-armv.S is used to achieve atomic functions. See bug
- * 478054 for details.
+ * work, while MS intrinsics (_Interlocked*) do not compile.
*/
#ifndef _ATOMIC_H_
@@ -49,9 +43,198 @@
#include "includeCheck.h"
#include "vm_basic_types.h"
+#include "vm_assert.h"
+/*
+ * In the Atomic_* definitions below, memory ordering and atomicity are somewhat
+ * conflated in an inconsistent manner. First, we have Atomic_{Read,Write},
+ * which only guarantees single copy atomicity, i.e. that the read/write occurs
+ * in an atomic fashion, but have no implication on memory ordering. The second
+ * class of Atomics are all the non-unfenced operations excluding
+ * Atomic_{Read,Write}*, which both imply atomicity and act as a memory barrier,
+ * implying sequentially consistent ordering of the atomic operation with all
+ * loads/stores prior to and after it.
+ *
+ * Since on x86, the second class of operations are associated with LOCK
+ * semantics, assumptions have been made about the ordering these operations
+ * imply on surrounding code (see for example the vmkernel's RefCount
+ * implementation). As a result, on arm64 we have to provide these same
+ * guarantees. We do this by making use of DMB barriers both before and after
+ * the atomic ldrx/strx sequences. A barrier before and after is required to
+ * avoid having part of the atomic operation reordered with surrounding code,
+ * e.g. a store-load reordering of the strx with a following load outside the
+ * Atomic_ op. For the first class of operations, Atomic_{Read,Write}, we do not
+ * implement a barrier.
+ *
+ * This implementation of Atomic operations is suboptimal on arm64, since
+ * both atomicity and memory ordering are fused together. Ideally the Atomic
+ * operations would only imply atomicity, and an explicit memory barrier in the
+ * surrounding code used to enforce ordering where necessary. This would eschew
+ * the need for the DMBs. A middle ground can be implemented where we use the
+ * arm64 load-acquire/store-release exclusive instructions to implement Atomics.
+ * This would imply sequential consistency of the Atomic operations (but not
+ * with any of the surrounding non-atomic operations) without the need for a
+ * DMB. Using these without a DMB today can still result in problematic
+ * reordering by the processor with surrounding non-atomic operations, e.g. a
+ * store-load reordering with a stlxr. Future optimization for arm64 should
+ * consider the wider change required at the call sites to minimize DMBs.
+ *
+ * For further details on x86 and ARM memory ordering see
+ * https://wiki.eng.vmware.com/ARM/MemoryOrdering.
+ */
+
+#ifdef VM_ARM_64
+#include "vm_basic_asm_arm64.h"
+
+#define ARM_64_ATOMIC_16_OPV_PRIVATE(atm,modval,op) ({ \
+ uint32 _failed; \
+ uint16 _sample; \
+ __asm__ __volatile__ ( \
+ "1: ldxrh %w0, [%2] \n\t" \
+ #op " %w0, %w0, %w3 \n\t" \
+ " stxrh %w1, %w0, [%2] \n\t" \
+ " cbnz %w1, 1b \n\t" \
+ : "=&r" (_sample), \
+ "=&r" (_failed) \
+ : "r" (atm), \
+ "r" (modval) \
+ : "memory"); \
+})
+
+#define ARM_64_ATOMIC_16_OPO_PRIVATE(atm,modval,op) ({ \
+ uint32 _failed; \
+ uint16 _newval; \
+ uint16 _oldval; \
+ __asm__ __volatile__ ( \
+ "1: ldxrh %w0, [%3] \n\t" \
+ #op " %w1, %w0, %w4 \n\t" \
+ " stxrh %w2, %w1, [%3] \n\t" \
+ " cbnz %w2, 1b \n\t" \
+ : "=&r" (_oldval), \
+ "=&r" (_newval), \
+ "=&r" (_failed) \
+ : "r" (atm), \
+ "r" (modval) \
+ : "memory"); \
+ _oldval; \
+})
+
+#define ARM_64_ATOMIC_32_OPV_PRIVATE(atm,modval,op) ({ \
+ uint32 _failed; \
+ uint32 _sample; \
+ __asm__ __volatile__ ( \
+ "1: ldxr %w0, [%2] \n\t" \
+ #op " %w0, %w0, %w3 \n\t" \
+ " stxr %w1, %w0, [%2] \n\t" \
+ " cbnz %w1, 1b \n\t" \
+ : "=&r" (_sample), \
+ "=&r" (_failed) \
+ : "r" (atm), \
+ "r" (modval) \
+ : "memory"); \
+})
+
+#define ARM_64_ATOMIC_32_OPO_PRIVATE(atm,modval,op) ({ \
+ uint32 _failed; \
+ uint32 _newval; \
+ uint32 _oldval; \
+ __asm__ __volatile__ ( \
+ "1: ldxr %w0, [%3] \n\t" \
+ #op " %w1, %w0, %w4 \n\t" \
+ " stxr %w2, %w1, [%3] \n\t" \
+ " cbnz %w2, 1b \n\t" \
+ : "=&r" (_oldval), \
+ "=&r" (_newval), \
+ "=&r" (_failed) \
+ : "r" (atm), \
+ "r" (modval) \
+ : "memory"); \
+ _oldval; \
+})
+
+#define ARM_64_ATOMIC_64_OPV_PRIVATE(atm,modval,op) ({ \
+ uint32 _failed; \
+ uint64 _sample; \
+ __asm__ __volatile__ ( \
+ "1: ldxr %x0, [%2] \n\t" \
+ #op " %x0, %x0, %x3 \n\t" \
+ " stxr %w1, %x0, [%2] \n\t" \
+ " cbnz %w1, 1b \n\t" \
+ : "=&r" (_sample), \
+ "=&r" (_failed) \
+ : "r" (atm), \
+ "r" (modval) \
+ : "memory"); \
+})
+
+#define ARM_64_ATOMIC_64_OPO_PRIVATE(atm,modval,op) ({ \
+ uint32 _failed; \
+ uint64 _newval; \
+ uint64 _oldval; \
+ __asm__ __volatile__ ( \
+ "1: ldxr %x0, [%3] \n\t" \
+ #op " %x1, %x0, %x4 \n\t" \
+ " stxr %w2, %x1, [%3] \n\t" \
+ " cbnz %w2, 1b \n\t" \
+ : "=&r" (_oldval), \
+ "=&r" (_newval), \
+ "=&r" (_failed) \
+ : "r" (atm), \
+ "r" (modval) \
+ : "memory"); \
+ _oldval; \
+})
+
+#define ARM_64_ATOMIC_16_OPV_PRIVATE_FENCED(atm,modval,op) ({ \
+ DMB(); \
+ ARM_64_ATOMIC_16_OPV_PRIVATE(atm,modval,op); \
+ DMB(); \
+})
+
+#define ARM_64_ATOMIC_16_OPO_PRIVATE_FENCED(atm,modval,op) ({ \
+ uint16 _oldval_fenced; \
+ DMB(); \
+ _oldval_fenced = ARM_64_ATOMIC_16_OPO_PRIVATE(atm,modval,op); \
+ DMB(); \
+ _oldval_fenced; \
+})
+
+#define ARM_64_ATOMIC_32_OPV_PRIVATE_FENCED(atm,modval,op) ({ \
+ DMB(); \
+ ARM_64_ATOMIC_32_OPV_PRIVATE(atm,modval,op); \
+ DMB(); \
+})
+
+#define ARM_64_ATOMIC_32_OPO_PRIVATE_FENCED(atm,modval,op) ({ \
+ uint32 _oldval_fenced; \
+ DMB(); \
+ _oldval_fenced = ARM_64_ATOMIC_32_OPO_PRIVATE(atm,modval,op); \
+ DMB(); \
+ _oldval_fenced; \
+})
+
+#define ARM_64_ATOMIC_64_OPV_PRIVATE_FENCED(atm,modval,op) ({ \
+ DMB(); \
+ ARM_64_ATOMIC_64_OPV_PRIVATE(atm,modval,op); \
+ DMB(); \
+})
+
+#define ARM_64_ATOMIC_64_OPO_PRIVATE_FENCED(atm,modval,op) ({ \
+ uint64 _oldval_fenced; \
+ DMB(); \
+ _oldval_fenced = ARM_64_ATOMIC_64_OPO_PRIVATE(atm,modval,op); \
+ DMB(); \
+ _oldval_fenced; \
+})
+
+#endif /* VM_ARM_64 */
+
+
+/* Basic atomic types: 16, 32 and 64 bits */
+typedef struct Atomic_uint16 {
+ volatile uint16 value;
+} Atomic_uint16 ALIGNED(2);
-/* Basic atomic types: 32 and 64 bits */
typedef struct Atomic_uint32 {
volatile uint32 value;
} Atomic_uint32 ALIGNED(4);
@@ -63,13 +246,13 @@ typedef struct Atomic_uint64 {
/*
* Prototypes for msft atomics. These are defined & inlined by the
* compiler so no function definition is needed. The prototypes are
- * needed for c++. Since amd64 compiler doesn't support inline asm we
+ * needed for C++. Since amd64 compiler doesn't support inline asm we
* have to use these. Unfortunately, we still have to use some inline asm
* for the 32 bit code since the and/or/xor implementations didn't show up
- * untill xp or 2k3.
+ * until XP or 2k3.
*
* The declarations for the intrinsic functions were taken from ntddk.h
- * in the DDK. The declarations must match otherwise the 64-bit c++
+ * in the DDK. The declarations must match otherwise the 64-bit C++
* compiler will complain about second linkage of the intrinsic functions.
* We define the intrinsic using the basic types corresponding to the
* Windows typedefs. This avoids having to include windows header files
@@ -89,6 +272,12 @@ void _ReadWriteBarrier(void);
#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedDecrement)
#pragma intrinsic(_InterlockedIncrement, _ReadWriteBarrier)
+# if _MSC_VER >= 1600
+char _InterlockedExchange8(char volatile *, char);
+char _InterlockedCompareExchange8(char volatile *, char, char);
+#pragma intrinsic(_InterlockedCompareExchange8, _InterlockedCompareExchange8)
+#endif
+
#if defined(VM_X86_64)
long _InterlockedAnd(long volatile*, long);
__int64 _InterlockedAnd64(__int64 volatile*, __int64);
@@ -146,14 +335,14 @@ __int64 _InterlockedCompareExchange64(__int64 volatile*, __int64, __int64);
/* Convert a volatile uint32 to Atomic_uint32. */
static INLINE Atomic_uint32 *
-Atomic_VolatileToAtomic(volatile uint32 *var)
+Atomic_VolatileToAtomic(volatile uint32 *var) // IN:
{
return (Atomic_uint32 *)var;
}
/* Convert a volatile uint64 to Atomic_uint64. */
static INLINE Atomic_uint64 *
-Atomic_VolatileToAtomic64(volatile uint64 *var)
+Atomic_VolatileToAtomic64(volatile uint64 *var) // IN:
{
return (Atomic_uint64 *)var;
}
@@ -212,7 +401,12 @@ Atomic_VolatileToAtomic64(volatile uint64 *var)
* dynamically enable the errata work-around. With vSphere 2017,
* this will no longer be required as the oldest version of ESX that
* VC 2017 will support is ESX 2014 (which won't run on Rev F).
+ *
+ * Modules may explicitly define MAY_NEED_AMD_REVF_WORKAROUND as 0 prior to
+ * inclusion of vm_atomic.h when they are safe on AMD Rev F with the elided
+ * lfence.
*/
+#if !defined(MAY_NEED_AMD_REVF_WORKAROUND)
#if (!defined(VMX86_SERVER) || \
(!defined(VMX86_VMX) && !defined(VMKERNEL) && \
!defined(VMM) && !defined(VMCORE)))
@@ -220,6 +414,7 @@ Atomic_VolatileToAtomic64(volatile uint64 *var)
#else
#define MAY_NEED_AMD_REVF_WORKAROUND 0
#endif
+#endif
#if MAY_NEED_AMD_REVF_WORKAROUND
#if defined(VMATOMIC_IMPORT_DLLDATA)
@@ -247,7 +442,7 @@ Atomic_Init(void)
}
static INLINE void
-Atomic_SetFence(Bool fenceAfterLock)
+Atomic_SetFence(Bool fenceAfterLock) // IN:
{
(void)fenceAfterLock; /* Work around unused parameter. */
#if MAY_NEED_AMD_REVF_WORKAROUND
@@ -317,6 +512,204 @@ AtomicEpilogue(void)
* - walken
*/
+#if defined(_MSC_VER) && _MSC_VER < 1600 && defined(__x86_64__)
+Bool VMWInterlockedExchangeBool(Bool volatile *ptr,
+ Bool val);
+
+Bool VMWInterlockedCompareExchangeBool(Bool volatile *ptr,
+ Bool newVal,
+ Bool oldVal);
+#endif
+
+typedef struct Atomic_Bool {
+ volatile Bool value;
+} Atomic_Bool;
+
+/* The ARM team can come along and add the code real soon now */
+extern Bool AtomicUndefinedOnARM(void);
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadBool --
+ *
+ * Read the value of the specified object atomically.
+ *
+ * Results:
+ * The value of the atomic variable.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+Atomic_ReadBool(Atomic_Bool const *var) // IN:
+{
+ Bool val;
+
+#if defined(__GNUC__) && (defined(VM_ARM_32) || defined(VM_ARM_64))
+ val = AtomicUndefinedOnARM();
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ __asm__ __volatile__(
+ "movb %1, %0"
+ : "=q" (val)
+ : "m" (var->value)
+ );
+#elif defined(_MSC_VER)
+ val = var->value;
+#else
+#error No compiler defined for Atomic_ReadBool
+#endif
+
+ return val;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadWriteBool --
+ *
+ * Read followed by write.
+ *
+ * Results:
+ * The value of the atomic variable before the write.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+Atomic_ReadWriteBool(Atomic_Bool *var, // IN/OUT:
+ Bool val) // IN:
+{
+#if defined(__GNUC__) && (defined(VM_ARM_32) || defined(VM_ARM_64))
+ return AtomicUndefinedOnARM();
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ __asm__ __volatile__(
+ "xchgb %0, %1"
+ : "=q" (val),
+ "+m" (var->value)
+ : "0" (val)
+ );
+ AtomicEpilogue();
+ return val;
+#elif defined(_MSC_VER) && _MSC_VER >= 1600
+ return _InterlockedExchange8(&var->value, val);
+#elif defined(_MSC_VER) && defined(__i386__)
+#pragma warning(push)
+#pragma warning(disable : 4035) // disable no-return warning
+ {
+ __asm movzx eax, val
+ __asm mov ebx, var
+ __asm xchg [ebx]Atomic_Bool.value, al
+ }
+#pragma warning(pop)
+#elif defined(_MSC_VER) && defined(__x86_64__)
+ return VMWInterlockedExchangeBool(&var->value, val);
+#else
+#error No compiler defined for Atomic_ReadBool
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_WriteBool --
+ *
+ * Write the specified value to the specified object atomically.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_WriteBool(Atomic_Bool *var, // IN/OUT:
+ Bool val) // IN:
+{
+#if defined(__GNUC__) && (defined(VM_ARM_32) || defined(VM_ARM_64))
+ AtomicUndefinedOnARM();
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ __asm__ __volatile__(
+ "movb %1, %0"
+ : "=m" (var->value)
+ : "qn" (val)
+ );
+#elif defined(_MSC_VER)
+ var->value = val;
+#else
+#error No compiler defined for Atomic_WriteBool
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadIfEqualWriteBool --
+ *
+ * Compare exchange: Read variable, if equal to oldVal, write newVal.
+ *
+ * Results:
+ * The value of the atomic variable before the write.
+ *
+ * Side effects:
+ * The variable may be modified.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+Atomic_ReadIfEqualWriteBool(Atomic_Bool *var, // IN/OUT:
+ Bool oldVal, // IN:
+ Bool newVal) // IN:
+{
+#if defined(__GNUC__) && (defined(VM_ARM_32) || defined(VM_ARM_64))
+ return AtomicUndefinedOnARM();
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ Bool val;
+
+ __asm__ __volatile__(
+ "lock; cmpxchgb %2, %1"
+ : "=a" (val),
+ "+m" (var->value)
+ : "q" (newVal),
+ "0" (oldVal)
+ : "cc"
+ );
+ AtomicEpilogue();
+ return val;
+#elif defined(_MSC_VER) && _MSC_VER >= 1600
+ return _InterlockedCompareExchange8(&var->value, newVal, oldVal);
+#elif defined(_MSC_VER) && defined(__i386__)
+#pragma warning(push)
+#pragma warning(disable : 4035) // disable no-return warning
+ {
+ __asm mov al, oldVal
+ __asm mov ebx, var
+ __asm mov cl, newVal
+ __asm lock cmpxchg [ebx]Atomic_Bool.value, cl
+ __asm movzx eax, al
+ // eax is the return value, this is documented to work - edward
+ }
+#pragma warning(pop)
+#elif defined(_MSC_VER) && defined(__x86_64__)
+ return VMWInterlockedCompareExchangeBool(&var->value, newVal, oldVal);
+#else
+#error No compiler defined for Atomic_ReadIfEqualWriteBool
+#endif
+}
+
/*
*-----------------------------------------------------------------------------
@@ -350,11 +743,17 @@ Atomic_Read(Atomic_uint32 const *var) // IN
* instructions.
*/
-#if defined(VM_ARM_V7)
+#if defined(VM_ARM_32)
__asm__ __volatile__(
"ldr %0, [%1]"
: "=r" (value)
- : "r" (var->value)
+ : "r" (&var->value)
+ );
+#elif defined(VM_ARM_64)
+ __asm__ __volatile__ (
+ "ldr %w0, [%1]"
+ : "=r" (value)
+ : "r" (&var->value)
);
#else
__asm__ __volatile__(
@@ -397,7 +796,7 @@ Atomic_Read(Atomic_uint32 const *var) // IN
*/
static INLINE uint32
-Atomic_ReadWrite(Atomic_uint32 *var, // IN
+Atomic_ReadWrite(Atomic_uint32 *var, // IN/OUT
uint32 val) // IN
{
#if defined(__GNUC__)
@@ -420,7 +819,23 @@ Atomic_ReadWrite(Atomic_uint32 *var, // IN
dmb();
return retVal;
-#else // __VM_ARM_V7 (assume x86*)
+#elif defined(VM_ARM_64)
+ register uint32 retVal;
+ register uint32 failed;
+
+ __asm__ __volatile__(
+ " dmb sy \n\t"
+ "1: ldxr %w0, [%2] \n\t"
+ " stxr %w1, %w3, [%2] \n\t"
+ " cbnz %w1, 1b \n\t"
+ " dmb sy \n\t"
+ : "=&r" (retVal), "=&r" (failed)
+ : "r" (&var->value), "r" (val)
+ : "memory"
+ );
+
+ return retVal;
+#else /* VM_X86_ANY */
/* Checked against the Intel manual and GCC --walken */
__asm__ __volatile__(
"xchgl %0, %1"
@@ -430,7 +845,7 @@ Atomic_ReadWrite(Atomic_uint32 *var, // IN
);
AtomicEpilogue();
return val;
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if _MSC_VER >= 1310
return _InterlockedExchange((long *)&var->value, (long)val);
@@ -469,7 +884,7 @@ Atomic_ReadWrite(Atomic_uint32 *var, // IN
*/
static INLINE void
-Atomic_Write(Atomic_uint32 *var, // IN
+Atomic_Write(Atomic_uint32 *var, // OUT
uint32 val) // IN
{
#if defined(VMM)
@@ -477,7 +892,7 @@ Atomic_Write(Atomic_uint32 *var, // IN
#endif
#if defined(__GNUC__)
-#if defined(VM_ARM_V7)
+#if defined(VM_ARM_ANY)
/*
* A3.4.1 ARM DDI 0406C:
*
@@ -495,9 +910,9 @@ Atomic_Write(Atomic_uint32 *var, // IN
* If two STREX instructions are executed without an intervening LDREX the
* second STREX returns a status value of 1. This means that:
*
- * — ARM recommends that, in a given thread of execution, every STREX has a
+ * - ARM recommends that, in a given thread of execution, every STREX has a
* preceding LDREX associated with it
- * — it is not necessary for every LDREX to have a subsequent STREX.
+ * - it is not necessary for every LDREX to have a subsequent STREX.
*/
Atomic_ReadWrite(var, val);
@@ -546,7 +961,7 @@ Atomic_Write(Atomic_uint32 *var, // IN
*/
static INLINE uint32
-Atomic_ReadIfEqualWrite(Atomic_uint32 *var, // IN
+Atomic_ReadIfEqualWrite(Atomic_uint32 *var, // IN/OUT
uint32 oldVal, // IN
uint32 newVal) // IN
{
@@ -572,7 +987,25 @@ Atomic_ReadIfEqualWrite(Atomic_uint32 *var, // IN
dmb();
return retVal;
-#else // VM_ARM_V7 (assume x86*)
+#elif defined(VM_ARM_64)
+ register uint32 retVal;
+ register uint32 failed;
+
+ __asm__ __volatile__ (
+ " dmb sy \n\t"
+ "1: ldxr %w0, [%2] \n\t"
+ " cmp %w0, %w3 \n\t"
+ " b.ne 2f \n\t"
+ " stxr %w1, %w4, [%2] \n\t"
+ " cbnz %w1, 1b \n\t"
+ "2: clrex \n\t"
+ " dmb sy \n\t"
+ : "=&r" (retVal), "=&r" (failed)
+ : "r" (&var->value), "r" (oldVal), "r" (newVal)
+ : "cc", "memory");
+
+ return retVal;
+#else /* VM_X86_ANY */
uint32 val;
/* Checked against the Intel manual and GCC --walken */
@@ -586,7 +1019,7 @@ Atomic_ReadIfEqualWrite(Atomic_uint32 *var, // IN
);
AtomicEpilogue();
return val;
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if _MSC_VER >= 1310
return _InterlockedCompareExchange((long *)&var->value,
@@ -611,7 +1044,7 @@ Atomic_ReadIfEqualWrite(Atomic_uint32 *var, // IN
#define Atomic_ReadIfEqualWrite32 Atomic_ReadIfEqualWrite
-#if defined(__x86_64__) || defined(VM_ARM_V7)
+#if defined(VM_64BIT) || defined(VM_ARM_V7)
/*
*-----------------------------------------------------------------------------
*
@@ -629,7 +1062,7 @@ Atomic_ReadIfEqualWrite(Atomic_uint32 *var, // IN
*/
static INLINE uint64
-Atomic_ReadIfEqualWrite64(Atomic_uint64 *var, // IN
+Atomic_ReadIfEqualWrite64(Atomic_uint64 *var, // IN/OUT
uint64 oldVal, // IN
uint64 newVal) // IN
{
@@ -640,6 +1073,24 @@ Atomic_ReadIfEqualWrite64(Atomic_uint64 *var, // IN
dmb();
+ /*
+ * Under Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
+ * There will be a warning:
+ * "value size does not match register size specified by the constraint
+ * and modifier [-Wasm-operand-widths]"
+ * on the lines:
+ * : [var] "r" (&var->value), [oldVal] "r" (oldVal), [newVal] "r" (newVal)
+ * ^
+ * : [var] "r" (&var->value), [oldVal] "r" (oldVal), [newVal] "r" (newVal)
+ * ^
+ *
+ * Furthermore, using a 32-bits register to store a
+ * 64-bits value of an variable looks risky.
+ */
+#if defined(__APPLE__) && __clang__ == 1 && __clang_major__ >= 5
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wasm-operand-widths"
+#endif
__asm__ __volatile__(
"1: ldrexd %[retVal], %H[retVal], [%[var]] \n\t"
"mov %[res], #0 \n\t"
@@ -652,11 +1103,31 @@ Atomic_ReadIfEqualWrite64(Atomic_uint64 *var, // IN
: [var] "r" (&var->value), [oldVal] "r" (oldVal), [newVal] "r" (newVal)
: "cc"
);
-
+#if defined(__APPLE__) && __clang__ == 1 && __clang_major__ >= 5
+#pragma clang diagnostic pop
+#endif // defined(__APPLE__) && __clang__ == 1 && __clang_major__ >= 5
dmb();
return retVal;
-#else // VM_ARM_V7 (assume x86*)
+#elif defined(VM_ARM_64)
+ register uint64 retVal;
+ register uint32 failed;
+
+ __asm__ __volatile__ (
+ " dmb sy \n\t"
+ "1: ldxr %x0, [%2] \n\t"
+ " cmp %x0, %x3 \n\t"
+ " b.ne 2f \n\t"
+ " stxr %w1, %x4, [%2] \n\t"
+ " cbnz %w1, 1b \n\t"
+ "2: clrex \n\t"
+ " dmb sy \n\t"
+ : "=&r" (retVal), "=&r" (failed)
+ : "r" (&var->value), "r" (oldVal), "r" (newVal)
+ : "cc", "memory");
+
+ return retVal;
+#else /* VM_X86_64 */
uint64 val;
/* Checked against the AMD manual and GCC --hpreg */
@@ -699,7 +1170,7 @@ Atomic_ReadIfEqualWrite64(Atomic_uint64 *var, // IN
*/
static INLINE void
-Atomic_And(Atomic_uint32 *var, // IN
+Atomic_And(Atomic_uint32 *var, // IN/OUT
uint32 val) // IN
{
#if defined(__GNUC__)
@@ -721,7 +1192,9 @@ Atomic_And(Atomic_uint32 *var, // IN
);
dmb();
-#else /* VM_ARM_V7 */
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_32_OPV_PRIVATE_FENCED(var, val, and);
+#else /* VM_X86_ANY */
/* Checked against the Intel manual and GCC --walken */
__asm__ __volatile__(
"lock; andl %1, %0"
@@ -730,7 +1203,7 @@ Atomic_And(Atomic_uint32 *var, // IN
: "cc"
);
AtomicEpilogue();
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if defined(__x86_64__)
_InterlockedAnd((long *)&var->value, (long)val);
@@ -763,7 +1236,7 @@ Atomic_And(Atomic_uint32 *var, // IN
*/
static INLINE void
-Atomic_Or(Atomic_uint32 *var, // IN
+Atomic_Or(Atomic_uint32 *var, // IN/OUT
uint32 val) // IN
{
#if defined(__GNUC__)
@@ -785,7 +1258,9 @@ Atomic_Or(Atomic_uint32 *var, // IN
);
dmb();
-#else // VM_ARM_V7
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_32_OPV_PRIVATE_FENCED(var, val, orr);
+#else /* VM_X86_ANY */
/* Checked against the Intel manual and GCC --walken */
__asm__ __volatile__(
"lock; orl %1, %0"
@@ -794,7 +1269,7 @@ Atomic_Or(Atomic_uint32 *var, // IN
: "cc"
);
AtomicEpilogue();
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if defined(__x86_64__)
_InterlockedOr((long *)&var->value, (long)val);
@@ -827,7 +1302,7 @@ Atomic_Or(Atomic_uint32 *var, // IN
*/
static INLINE void
-Atomic_Xor(Atomic_uint32 *var, // IN
+Atomic_Xor(Atomic_uint32 *var, // IN/OUT
uint32 val) // IN
{
#if defined(__GNUC__)
@@ -849,7 +1324,9 @@ Atomic_Xor(Atomic_uint32 *var, // IN
);
dmb();
-#else // VM_ARM_V7
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_32_OPV_PRIVATE_FENCED(var, val, eor);
+#else /* VM_X86_ANY */
/* Checked against the Intel manual and GCC --walken */
__asm__ __volatile__(
"lock; xorl %1, %0"
@@ -858,7 +1335,7 @@ Atomic_Xor(Atomic_uint32 *var, // IN
: "cc"
);
AtomicEpilogue();
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if defined(__x86_64__)
_InterlockedXor((long *)&var->value, (long)val);
@@ -874,7 +1351,7 @@ Atomic_Xor(Atomic_uint32 *var, // IN
#define Atomic_Xor32 Atomic_Xor
-#if defined(__x86_64__)
+#if defined(VM_64BIT)
/*
*-----------------------------------------------------------------------------
*
@@ -892,10 +1369,13 @@ Atomic_Xor(Atomic_uint32 *var, // IN
*/
static INLINE void
-Atomic_Xor64(Atomic_uint64 *var, // IN
+Atomic_Xor64(Atomic_uint64 *var, // IN/OUT
uint64 val) // IN
{
#if defined(__GNUC__)
+#if defined(VM_ARM_64)
+ ARM_64_ATOMIC_64_OPV_PRIVATE_FENCED(var, val, eor);
+#else /* VM_X86_64 */
/* Checked against the AMD manual and GCC --hpreg */
__asm__ __volatile__(
"lock; xorq %1, %0"
@@ -904,6 +1384,7 @@ Atomic_Xor64(Atomic_uint64 *var, // IN
: "cc"
);
AtomicEpilogue();
+#endif
#elif defined _MSC_VER
_InterlockedXor64((__int64 *)&var->value, (__int64)val);
#else
@@ -930,7 +1411,7 @@ Atomic_Xor64(Atomic_uint64 *var, // IN
*/
static INLINE void
-Atomic_Add(Atomic_uint32 *var, // IN
+Atomic_Add(Atomic_uint32 *var, // IN/OUT
uint32 val) // IN
{
#if defined(__GNUC__)
@@ -952,7 +1433,9 @@ Atomic_Add(Atomic_uint32 *var, // IN
);
dmb();
-#else // VM_ARM_V7
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_32_OPV_PRIVATE_FENCED(var, val, add);
+#else /* VM_X86_ANY */
/* Checked against the Intel manual and GCC --walken */
__asm__ __volatile__(
"lock; addl %1, %0"
@@ -961,7 +1444,7 @@ Atomic_Add(Atomic_uint32 *var, // IN
: "cc"
);
AtomicEpilogue();
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if _MSC_VER >= 1310
_InterlockedExchangeAdd((long *)&var->value, (long)val);
@@ -994,7 +1477,7 @@ Atomic_Add(Atomic_uint32 *var, // IN
*/
static INLINE void
-Atomic_Sub(Atomic_uint32 *var, // IN
+Atomic_Sub(Atomic_uint32 *var, // IN/OUT
uint32 val) // IN
{
#if defined(__GNUC__)
@@ -1016,7 +1499,9 @@ Atomic_Sub(Atomic_uint32 *var, // IN
);
dmb();
-#else // VM_ARM_V7
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_32_OPV_PRIVATE_FENCED(var, val, sub);
+#else /* VM_X86_ANY */
/* Checked against the Intel manual and GCC --walken */
__asm__ __volatile__(
"lock; subl %1, %0"
@@ -1025,7 +1510,7 @@ Atomic_Sub(Atomic_uint32 *var, // IN
: "cc"
);
AtomicEpilogue();
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if _MSC_VER >= 1310
_InterlockedExchangeAdd((long *)&var->value, (long)-val);
@@ -1058,12 +1543,12 @@ Atomic_Sub(Atomic_uint32 *var, // IN
*/
static INLINE void
-Atomic_Inc(Atomic_uint32 *var) // IN
+Atomic_Inc(Atomic_uint32 *var) // IN/OUT
{
#ifdef __GNUC__
-#if defined(VM_ARM_V7)
+#if defined(VM_ARM_ANY)
Atomic_Add(var, 1);
-#else // VM_ARM_V7
+#else /* VM_X86_ANY */
/* Checked against the Intel manual and GCC --walken */
__asm__ __volatile__(
"lock; incl %0"
@@ -1072,7 +1557,7 @@ Atomic_Inc(Atomic_uint32 *var) // IN
: "cc"
);
AtomicEpilogue();
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if _MSC_VER >= 1310
_InterlockedIncrement((long *)&var->value);
@@ -1104,12 +1589,12 @@ Atomic_Inc(Atomic_uint32 *var) // IN
*/
static INLINE void
-Atomic_Dec(Atomic_uint32 *var) // IN
+Atomic_Dec(Atomic_uint32 *var) // IN/OUT
{
#ifdef __GNUC__
-#if defined(VM_ARM_V7)
+#if defined(VM_ARM_ANY)
Atomic_Sub(var, 1);
-#else // VM_ARM_V7
+#else /* VM_X86_ANY */
/* Checked against the Intel manual and GCC --walken */
__asm__ __volatile__(
"lock; decl %0"
@@ -1118,7 +1603,7 @@ Atomic_Dec(Atomic_uint32 *var) // IN
: "cc"
);
AtomicEpilogue();
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if _MSC_VER >= 1310
_InterlockedDecrement((long *)&var->value);
@@ -1156,7 +1641,7 @@ Atomic_Dec(Atomic_uint32 *var) // IN
*/
static INLINE uint32
-Atomic_ReadOr32(Atomic_uint32 *var, // IN
+Atomic_ReadOr32(Atomic_uint32 *var, // IN/OUT
uint32 val) // IN
{
uint32 res;
@@ -1186,7 +1671,7 @@ Atomic_ReadOr32(Atomic_uint32 *var, // IN
*/
static INLINE uint32
-Atomic_ReadAnd32(Atomic_uint32 *var, // IN
+Atomic_ReadAnd32(Atomic_uint32 *var, // IN/OUT
uint32 val) // IN
{
uint32 res;
@@ -1199,7 +1684,7 @@ Atomic_ReadAnd32(Atomic_uint32 *var, // IN
}
-#if defined(__x86_64__)
+#if defined(VM_64BIT)
/*
*-----------------------------------------------------------------------------
*
@@ -1217,7 +1702,7 @@ Atomic_ReadAnd32(Atomic_uint32 *var, // IN
*/
static INLINE uint64
-Atomic_ReadOr64(Atomic_uint64 *var, // IN
+Atomic_ReadOr64(Atomic_uint64 *var, // IN/OUT
uint64 val) // IN
{
uint64 res;
@@ -1247,7 +1732,7 @@ Atomic_ReadOr64(Atomic_uint64 *var, // IN
*/
static INLINE uint64
-Atomic_ReadAnd64(Atomic_uint64 *var, // IN
+Atomic_ReadAnd64(Atomic_uint64 *var, // IN/OUT
uint64 val) // IN
{
uint64 res;
@@ -1258,13 +1743,13 @@ Atomic_ReadAnd64(Atomic_uint64 *var, // IN
return res;
}
-#endif // __x86_64__
+#endif /* defined(VM_64BIT) */
/*
*-----------------------------------------------------------------------------
*
- * Atomic_ReadAdd32Unfenced --
+ * Atomic_ReadAdd32 --
*
* Atomic read (returned), add a value, write.
*
@@ -1272,9 +1757,6 @@ Atomic_ReadAnd64(Atomic_uint64 *var, // IN
* x86 or x86-64, you might want to consider doing something similar to
* Atomic_ReadOr32().
*
- * The "Unfenced" version of Atomic_ReadAdd32 never executes
- * "lfence" after the interlocked operation.
- *
* Results:
* The value of the variable before the operation.
*
@@ -1285,8 +1767,8 @@ Atomic_ReadAnd64(Atomic_uint64 *var, // IN
*/
static INLINE uint32
-Atomic_ReadAdd32Unfenced(Atomic_uint32 *var, // IN
- uint32 val) // IN
+Atomic_ReadAdd32(Atomic_uint32 *var, // IN/OUT
+ uint32 val) // IN
{
#if defined(__GNUC__)
#ifdef VM_ARM_V7
@@ -1310,7 +1792,9 @@ Atomic_ReadAdd32Unfenced(Atomic_uint32 *var, // IN
dmb();
return retVal;
-#else // VM_ARM_V7
+#elif defined(VM_ARM_64)
+ return ARM_64_ATOMIC_32_OPO_PRIVATE_FENCED(var, val, add);
+#else /* VM_X86_ANY */
/* Checked against the Intel manual and GCC --walken */
__asm__ __volatile__(
"lock; xaddl %0, %1"
@@ -1319,8 +1803,9 @@ Atomic_ReadAdd32Unfenced(Atomic_uint32 *var, // IN
: "0" (val)
: "cc"
);
+ AtomicEpilogue();
return val;
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#elif defined _MSC_VER
#if _MSC_VER >= 1310
return _InterlockedExchangeAdd((long *)&var->value, (long)val);
@@ -1335,44 +1820,7 @@ Atomic_ReadAdd32Unfenced(Atomic_uint32 *var, // IN
#pragma warning(pop)
#endif
#else
-#error No compiler defined for Atomic_ReadAdd32Unfenced
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Atomic_ReadAdd32 --
- *
- * Atomic read (returned), add a value, write.
- *
- * If you have to implement ReadAdd32() on an architecture other than
- * x86 or x86-64, you might want to consider doing something similar to
- * Atomic_ReadOr32().
- *
- * Unlike "Unfenced" version, this one may execute the "lfence" after
- * interlocked operation.
- *
- * Results:
- * The value of the variable before the operation.
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-static INLINE uint32
-Atomic_ReadAdd32(Atomic_uint32 *var, // IN
- uint32 val) // IN
-{
-#if defined(__GNUC__) && !defined(VM_ARM_V7)
- val = Atomic_ReadAdd32Unfenced(var, val);
- AtomicEpilogue();
- return val;
-#else
- return Atomic_ReadAdd32Unfenced(var, val);
+#error No compiler defined for Atomic_ReadAdd32
#endif
}
@@ -1394,7 +1842,7 @@ Atomic_ReadAdd32(Atomic_uint32 *var, // IN
*/
static INLINE uint32
-Atomic_ReadInc32(Atomic_uint32 *var) // IN
+Atomic_ReadInc32(Atomic_uint32 *var) // IN/OUT
{
return Atomic_ReadAdd32(var, 1);
}
@@ -1417,13 +1865,14 @@ Atomic_ReadInc32(Atomic_uint32 *var) // IN
*/
static INLINE uint32
-Atomic_ReadDec32(Atomic_uint32 *var) // IN
+Atomic_ReadDec32(Atomic_uint32 *var) // IN/OUT
{
return Atomic_ReadAdd32(var, (uint32)-1);
}
#if defined VMKERNEL || defined VMM
+#if !defined(VM_ARM_64)
/*
*-----------------------------------------------------------------------------
*
@@ -1440,7 +1889,7 @@ Atomic_ReadDec32(Atomic_uint32 *var) // IN
*-----------------------------------------------------------------------------
*/
static INLINE uint8
-CMPXCHG1B(volatile uint8 *ptr, // IN
+CMPXCHG1B(volatile uint8 *ptr, // IN/OUT
uint8 oldVal, // IN
uint8 newVal) // IN
{
@@ -1453,6 +1902,7 @@ CMPXCHG1B(volatile uint8 *ptr, // IN
: "cc");
return val;
}
+#endif /* !defined(VM_ARM_64) */
#endif
@@ -1498,10 +1948,9 @@ Atomic_CMPXCHG64(Atomic_uint64 *var, // IN/OUT
uint64 const *newVal) // IN
{
#if defined(__GNUC__)
-#if defined(VM_ARM_V7)
+#if defined(VM_ARM_ANY)
return (Atomic_ReadIfEqualWrite64(var, *oldVal, *newVal) == *oldVal);
-
-#else // VM_ARM_V7
+#else /* VM_X86_ANY */
Bool equal;
/* Checked against the Intel manual and GCC --walken */
@@ -1657,13 +2106,13 @@ Atomic_CMPXCHG64(Atomic_uint64 *var, // IN/OUT
static INLINE Bool
Atomic_CMPXCHG32(Atomic_uint32 *var, // IN/OUT
- uint32 oldVal, // IN
- uint32 newVal) // IN
+ uint32 oldVal, // IN
+ uint32 newVal) // IN
{
#if defined(__GNUC__)
-#ifdef VM_ARM_V7
+#if defined(VM_ARM_ANY)
return (Atomic_ReadIfEqualWrite(var, oldVal, newVal) == oldVal);
-#else // VM_ARM_V7
+#else /* VM_X86_ANY */
Bool equal;
uint32 dummy;
@@ -1679,7 +2128,7 @@ Atomic_CMPXCHG32(Atomic_uint32 *var, // IN/OUT
);
AtomicEpilogue();
return equal;
-#endif // VM_ARM_V7
+#endif /* VM_X86_ANY */
#else // defined(__GNUC__)
return (Atomic_ReadIfEqualWrite(var, oldVal, newVal) == oldVal);
#endif // !defined(__GNUC__)
@@ -1771,7 +2220,16 @@ Atomic_Read64(Atomic_uint64 const *var) // IN
);
return value;
-#endif
+#elif defined(__GNUC__) && defined(VM_ARM_64)
+ uint64 value;
+
+ __asm__ __volatile__(
+ "ldr %0, [%1]"
+ : "=r" (value)
+ : "r" (&var->value));
+
+ return value;
+#endif /* defined(__GNUC__) && defined(VM_ARM_64) */
}
@@ -1795,9 +2253,10 @@ Atomic_Read64(Atomic_uint64 const *var) // IN
*
*----------------------------------------------------------------------
*/
-#if defined(__x86_64__)
+
+#if defined(VM_64BIT)
static INLINE uint64
-Atomic_ReadUnaligned64(Atomic_uint64 const *var)
+Atomic_ReadUnaligned64(Atomic_uint64 const *var) // IN:
{
return Atomic_ReadIfEqualWrite64((Atomic_uint64*)var, 0, 0);
}
@@ -1824,7 +2283,9 @@ static INLINE uint64
Atomic_ReadAdd64(Atomic_uint64 *var, // IN/OUT
uint64 val) // IN
{
-#if defined(__x86_64__)
+#if defined(VM_ARM_64)
+ return ARM_64_ATOMIC_64_OPO_PRIVATE_FENCED(var, val, add);
+#elif defined(__x86_64__)
#if defined(__GNUC__)
__asm__ __volatile__(
@@ -1943,12 +2404,15 @@ Atomic_ReadDec64(Atomic_uint64 *var) // IN/OUT
*/
static INLINE void
-Atomic_Add64(Atomic_uint64 *var, // IN
+Atomic_Add64(Atomic_uint64 *var, // IN/OUT
uint64 val) // IN
{
-#if !defined(__x86_64__)
+#if !defined(VM_64BIT)
Atomic_ReadAdd64(var, val); /* Return value is unused. */
#elif defined(__GNUC__)
+#if defined(VM_ARM_64)
+ ARM_64_ATOMIC_64_OPV_PRIVATE_FENCED(var, val, add);
+#else /* defined(VM_X86_64) */
/* Checked against the AMD manual and GCC --hpreg */
__asm__ __volatile__(
"lock; addq %1, %0"
@@ -1957,6 +2421,7 @@ Atomic_Add64(Atomic_uint64 *var, // IN
: "cc"
);
AtomicEpilogue();
+#endif
#elif defined _MSC_VER
_InterlockedExchangeAdd64((__int64 *)&var->value, (__int64)val);
#else
@@ -1982,12 +2447,15 @@ Atomic_Add64(Atomic_uint64 *var, // IN
*/
static INLINE void
-Atomic_Sub64(Atomic_uint64 *var, // IN
+Atomic_Sub64(Atomic_uint64 *var, // IN/OUT
uint64 val) // IN
{
#if !defined(__x86_64__)
Atomic_ReadSub64(var, val); /* Return value is unused. */
#elif defined(__GNUC__)
+#if defined(VM_ARM_64)
+ ARM_64_ATOMIC_64_OPV_PRIVATE_FENCED(var, val, sub);
+#else /* VM_X86_64 */
/* Checked against the AMD manual and GCC --hpreg */
__asm__ __volatile__(
"lock; subq %1, %0"
@@ -1996,6 +2464,7 @@ Atomic_Sub64(Atomic_uint64 *var, // IN
: "cc"
);
AtomicEpilogue();
+#endif
#elif defined _MSC_VER
_InterlockedExchangeAdd64((__int64 *)&var->value, (__int64)-val);
#else
@@ -2021,7 +2490,7 @@ Atomic_Sub64(Atomic_uint64 *var, // IN
*/
static INLINE void
-Atomic_Inc64(Atomic_uint64 *var) // IN
+Atomic_Inc64(Atomic_uint64 *var) // IN/OUT
{
#if !defined(__x86_64__)
Atomic_ReadInc64(var); /* Return value is unused. */
@@ -2059,7 +2528,7 @@ Atomic_Inc64(Atomic_uint64 *var) // IN
*/
static INLINE void
-Atomic_Dec64(Atomic_uint64 *var) // IN
+Atomic_Dec64(Atomic_uint64 *var) // IN/OUT
{
#if !defined(__x86_64__)
Atomic_ReadDec64(var); /* Return value is unused. */
@@ -2097,7 +2566,7 @@ Atomic_Dec64(Atomic_uint64 *var) // IN
*/
static INLINE uint64
-Atomic_ReadWrite64(Atomic_uint64 *var, // IN
+Atomic_ReadWrite64(Atomic_uint64 *var, // IN/OUT
uint64 val) // IN
{
#if defined(__x86_64__)
@@ -2145,7 +2614,7 @@ Atomic_ReadWrite64(Atomic_uint64 *var, // IN
*/
static INLINE void
-Atomic_Write64(Atomic_uint64 *var, // IN
+Atomic_Write64(Atomic_uint64 *var, // OUT
uint64 val) // IN
{
#if defined(__x86_64__)
@@ -2202,7 +2671,7 @@ Atomic_Write64(Atomic_uint64 *var, // IN
*/
static INLINE void
-Atomic_Or64(Atomic_uint64 *var, // IN
+Atomic_Or64(Atomic_uint64 *var, // IN/OUT
uint64 val) // IN
{
#if defined(__x86_64__)
@@ -2248,7 +2717,7 @@ Atomic_Or64(Atomic_uint64 *var, // IN
*/
static INLINE void
-Atomic_And64(Atomic_uint64 *var, // IN
+Atomic_And64(Atomic_uint64 *var, // IN/OUT
uint64 val) // IN
{
#if defined(__x86_64__)
@@ -2282,9 +2751,7 @@ Atomic_And64(Atomic_uint64 *var, // IN
*
* Atomic_SetBit64 --
*
- * Atomic read, set bit N, and write.
- * Be careful: if bit is in a register (not in an immediate), then it
- * can specify a bit offset above 63 or even a negative offset.
+ * Atomically set the bit 'bit' in var. Bit must be between 0 and 63.
*
* Results:
* None
@@ -2294,12 +2761,14 @@ Atomic_And64(Atomic_uint64 *var, // IN
*
*-----------------------------------------------------------------------------
*/
+
static INLINE void
Atomic_SetBit64(Atomic_uint64 *var, // IN/OUT
uint64 bit) // IN
{
#if defined(__x86_64__)
#if defined(__GNUC__)
+ ASSERT(bit <= 63);
__asm__ __volatile__(
"lock; bts %1, %0"
: "+m" (var->value)
@@ -2310,6 +2779,7 @@ Atomic_SetBit64(Atomic_uint64 *var, // IN/OUT
#elif defined _MSC_VER
uint64 oldVal;
uint64 newVal;
+ ASSERT(bit <= 63);
do {
oldVal = var->value;
newVal = oldVal | (CONST64U(1) << bit);
@@ -2320,6 +2790,7 @@ Atomic_SetBit64(Atomic_uint64 *var, // IN/OUT
#else // __x86_64__
uint64 oldVal;
uint64 newVal;
+ ASSERT(bit <= 63);
do {
oldVal = var->value;
newVal = oldVal | (CONST64U(1) << bit);
@@ -2333,9 +2804,7 @@ Atomic_SetBit64(Atomic_uint64 *var, // IN/OUT
*
* Atomic_ClearBit64 --
*
- * Atomic read, clear bit N, and write.
- * Be careful: if bit is in a register (not in an immediate), then it
- * can specify a bit offset above 63 or even a negative offset.
+ * Atomically clear the bit 'bit' in var. Bit must be between 0 and 63.
*
* Results:
* None
@@ -2345,12 +2814,14 @@ Atomic_SetBit64(Atomic_uint64 *var, // IN/OUT
*
*-----------------------------------------------------------------------------
*/
+
static INLINE void
Atomic_ClearBit64(Atomic_uint64 *var, // IN/OUT
uint64 bit) // IN
{
#if defined(__x86_64__)
#if defined(__GNUC__)
+ ASSERT(bit <= 63);
__asm__ __volatile__(
"lock; btr %1, %0"
: "+m" (var->value)
@@ -2361,6 +2832,7 @@ Atomic_ClearBit64(Atomic_uint64 *var, // IN/OUT
#elif defined _MSC_VER
uint64 oldVal;
uint64 newVal;
+ ASSERT(bit <= 63);
do {
oldVal = var->value;
newVal = oldVal & ~(CONST64U(1) << bit);
@@ -2371,6 +2843,7 @@ Atomic_ClearBit64(Atomic_uint64 *var, // IN/OUT
#else // __x86_64__
uint64 oldVal;
uint64 newVal;
+ ASSERT(bit <= 63);
do {
oldVal = var->value;
newVal = oldVal & ~(CONST64U(1) << bit);
@@ -2384,9 +2857,7 @@ Atomic_ClearBit64(Atomic_uint64 *var, // IN/OUT
*
* Atomic_TestBit64 --
*
- * Read a bit.
- * Be careful: if bit is in a register (not in an immediate), then it
- * can specify a bit offset above 63 or even a negative offset.
+ * Read the bit 'bit' in var. Bit must be between 0 and 63.
*
* Results:
* TRUE if the tested bit was set; else FALSE.
@@ -2396,6 +2867,7 @@ Atomic_ClearBit64(Atomic_uint64 *var, // IN/OUT
*
*-----------------------------------------------------------------------------
*/
+
static INLINE Bool
Atomic_TestBit64(Atomic_uint64 *var, // IN
uint64 bit) // IN
@@ -2403,6 +2875,7 @@ Atomic_TestBit64(Atomic_uint64 *var, // IN
#if defined(__x86_64__)
#if defined(__GNUC__)
Bool out = FALSE;
+ ASSERT(bit <= 63);
__asm__ __volatile__(
"bt %2, %1; setc %0"
: "=rm"(out)
@@ -2412,15 +2885,776 @@ Atomic_TestBit64(Atomic_uint64 *var, // IN
);
return out;
#elif defined _MSC_VER
+ ASSERT(bit <= 63);
return (var->value & (CONST64U(1) << bit)) != 0;
#else
#error No compiler defined for Atomic_TestBit64
#endif
#else // __x86_64__
+ ASSERT(bit <= 63);
return (var->value & (CONST64U(1) << bit)) != 0;
#endif
}
+
+#if defined(__GNUC__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Read16 --
+ *
+ * Read and return.
+ *
+ * Results:
+ * The value of the atomic variable.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint16
+Atomic_Read16(Atomic_uint16 const *var) // IN
+{
+ uint16 value;
+
+#ifdef VMM
+ ASSERT((uintptr_t)var % 2 == 0);
+#endif
+
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+
+ __asm__ __volatile__(
+ "movw %1, %0"
+ : "=r" (value)
+ : "m" (var->value)
+ );
+#elif defined(VM_ARM_V7)
+ NOT_TESTED();
+
+ __asm__ __volatile__(
+ "ldrh %0, [%1]"
+ : "=r" (value)
+ : "r" (&var->value)
+ );
+#elif defined(VM_ARM_64)
+ __asm__ __volatile__ (
+ "ldrh %w0, [%1]"
+ : "=r" (value)
+ : "r" (&var->value)
+ );
+
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+
+ return value;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadWrite16 --
+ *
+ * Read followed by write
+ *
+ * Results:
+ * The value of the atomic variable before the write.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint16
+Atomic_ReadWrite16(Atomic_uint16 *var, // IN/OUT:
+ uint16 val) // IN:
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__(
+ "xchgw %0, %1"
+ : "=r" (val),
+ "+m" (var->value)
+ : "0" (val)
+ );
+ AtomicEpilogue();
+ return val;
+#elif defined(VM_ARM_V7)
+ register volatile uint16 retVal;
+ register volatile uint16 res;
+
+ NOT_TESTED();
+
+ dmb();
+
+ __asm__ __volatile__(
+ "1: ldrexh %[retVal], [%[var]] \n\t"
+ "strexh %[res], %[val], [%[var]] \n\t"
+ "teq %[res], #0 \n\t"
+ "bne 1b"
+ : [retVal] "=&r" (retVal), [res] "=&r" (res)
+ : [var] "r" (&var->value), [val] "r" (val)
+ : "cc"
+ );
+
+ dmb();
+
+ return retVal;
+#elif defined(VM_ARM_64)
+ register uint16 retVal;
+ register uint16 failed;
+
+ __asm__ __volatile__(
+ " dmb sy \n\t"
+ "1: ldxrh %w0, [%2] \n\t"
+ " stxrh %w1, %w3, [%2] \n\t"
+ " cbnz %w1, 1b \n\t"
+ " dmb sy \n\t"
+ : "=&r" (retVal), "=&r" (failed)
+ : "r" (&var->value), "r" (val)
+ : "memory"
+ );
+
+ return retVal;
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Write16 --
+ *
+ * Write
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Write16(Atomic_uint16 *var, // OUT:
+ uint16 val) // IN:
+{
+#ifdef VMM
+ ASSERT((uintptr_t)var % 2 == 0);
+#endif
+
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+
+ __asm__ __volatile__(
+ "movw %1, %0"
+ : "=m" (var->value)
+ : "r" (val)
+ );
+#elif defined(VM_ARM_ANY)
+ Atomic_ReadWrite16(var, val);
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadIfEqualWrite16 --
+ *
+ * Compare exchange: Read variable, if equal to oldVal, write newVal
+ *
+ * Results:
+ * The value of the atomic variable before the write.
+ *
+ * Side effects:
+ * The variable may be modified.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint16
+Atomic_ReadIfEqualWrite16(Atomic_uint16 *var, // IN/OUT
+ uint16 oldVal, // IN
+ uint16 newVal) // IN
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ uint16 val;
+
+ __asm__ __volatile__(
+ "lock; cmpxchgw %2, %1"
+ : "=a" (val),
+ "+m" (var->value)
+ : "r" (newVal),
+ "0" (oldVal)
+ : "cc"
+ );
+ AtomicEpilogue();
+ return val;
+#elif defined(VM_ARM_V7)
+ register uint16 retVal;
+ register uint16 res;
+
+ NOT_TESTED();
+
+ dmb();
+
+ __asm__ __volatile__(
+ "1: ldrexh %[retVal], [%[var]] \n\t"
+ "mov %[res], #0 \n\t"
+ "teq %[retVal], %[oldVal] \n\t"
+ "strexheq %[res], %[newVal], [%[var]] \n\t"
+ "teq %[res], #0 \n\t"
+ "bne 1b"
+ : [retVal] "=&r" (retVal), [res] "=&r" (res)
+ : [var] "r" (&var->value), [oldVal] "r" (oldVal), [newVal] "r" (newVal)
+ : "cc"
+ );
+
+ dmb();
+
+ return retVal;
+#elif defined(VM_ARM_64)
+ register uint16 retVal;
+ register uint16 failed;
+
+ __asm__ __volatile__ (
+ " dmb sy \n\t"
+ "1: ldxrh %w0, [%2] \n\t"
+ " cmp %w0, %w3 \n\t"
+ " b.ne 2f \n\t"
+ " stxrh %w1, %w4, [%2] \n\t"
+ " cbnz %w1, 1b \n\t"
+ "2: clrex \n\t"
+ " dmb sy \n\t"
+ : "=&r" (retVal), "=&r" (failed)
+ : "r" (&var->value), "r" (oldVal), "r" (newVal)
+ : "cc", "memory");
+
+ return retVal;
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_And16 --
+ *
+ * Atomic read, bitwise AND with a 16-bit value, write.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_And16(Atomic_uint16 *var, // IN/OUT
+ uint16 val) // IN
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__(
+ "lock; andw %1, %0"
+ : "+m" (var->value)
+ : "re" (val)
+ : "cc"
+ );
+ AtomicEpilogue();
+#elif defined(VM_ARM_V7)
+ register volatile uint16 res;
+ register volatile uint16 tmp;
+
+ NOT_TESTED();
+
+ dmb();
+
+ __asm__ __volatile__(
+ "1: ldrexh %[tmp], [%[var]] \n\t"
+ "and %[tmp], %[tmp], %[val] \n\t"
+ "strexh %[res], %[tmp], [%[var]] \n\t"
+ "teq %[res], #0 \n\t"
+ "bne 1b"
+ : [res] "=&r" (res), [tmp] "=&r" (tmp)
+ : [var] "r" (&var->value), [val] "r" (val)
+ : "cc"
+ );
+
+ dmb();
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_16_OPV_PRIVATE_FENCED(var, val, and);
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Or16 --
+ *
+ * Atomic read, bitwise OR with a 16-bit value, write.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Or16(Atomic_uint16 *var, // IN/OUT
+ uint16 val) // IN
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__(
+ "lock; orw %1, %0"
+ : "+m" (var->value)
+ : "re" (val)
+ : "cc"
+ );
+ AtomicEpilogue();
+#elif defined(VM_ARM_V7)
+ register volatile uint16 res;
+ register volatile uint16 tmp;
+
+ NOT_TESTED();
+
+ dmb();
+
+ __asm__ __volatile__(
+ "1: ldrexh %[tmp], [%[var]] \n\t"
+ "orr %[tmp], %[tmp], %[val] \n\t"
+ "strexh %[res], %[tmp], [%[var]] \n\t"
+ "teq %[res], #0 \n\t"
+ "bne 1b"
+ : [res] "=&r" (res), [tmp] "=&r" (tmp)
+ : [var] "r" (&var->value), [val] "r" (val)
+ : "cc"
+ );
+
+ dmb();
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_16_OPV_PRIVATE_FENCED(var, val, orr);
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Xor16 --
+ *
+ * Atomic read, bitwise XOR with a value, write.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Xor16(Atomic_uint16 *var, // IN/OUT
+ uint16 val) // IN
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__(
+ "lock; xorw %1, %0"
+ : "+m" (var->value)
+ : "re" (val)
+ : "cc"
+ );
+ AtomicEpilogue();
+#elif defined(VM_ARM_V7)
+ register volatile uint16 res;
+ register volatile uint16 tmp;
+
+ NOT_TESTED();
+
+ dmb();
+
+ __asm__ __volatile__(
+ "1: ldrexh %[tmp], [%[var]] \n\t"
+ "eor %[tmp], %[tmp], %[val] \n\t"
+ "strexh %[res], %[tmp], [%[var]] \n\t"
+ "teq %[res], #0 \n\t"
+ "bne 1b"
+ : [res] "=&r" (res), [tmp] "=&r" (tmp)
+ : [var] "r" (&var->value), [val] "r" (val)
+ : "cc"
+ );
+
+ dmb();
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_16_OPV_PRIVATE_FENCED(var, val, eor);
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Add16 --
+ *
+ * Atomic read, add a value, write.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Add16(Atomic_uint16 *var, // IN/OUT
+ uint16 val) // IN
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__(
+ "lock; addw %1, %0"
+ : "+m" (var->value)
+ : "re" (val)
+ : "cc"
+ );
+ AtomicEpilogue();
+#elif defined(VM_ARM_V7)
+ register volatile uint16 res;
+ register volatile uint16 tmp;
+
+ NOT_TESTED();
+
+ dmb();
+
+ __asm__ __volatile__(
+ "1: ldrexh %[tmp], [%[var]] \n\t"
+ "add %[tmp], %[tmp], %[val] \n\t"
+ "strexh %[res], %[tmp], [%[var]] \n\t"
+ "teq %[res], #0 \n\t"
+ "bne 1b"
+ : [res] "=&r" (res), [tmp] "=&r" (tmp)
+ : [var] "r" (&var->value), [val] "r" (val)
+ : "cc"
+ );
+
+ dmb();
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_16_OPV_PRIVATE_FENCED(var, val, add);
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Sub16 --
+ *
+ * Atomic read, subtract a value, write.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Sub16(Atomic_uint16 *var, // IN/OUT
+ uint16 val) // IN
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__(
+ "lock; subw %1, %0"
+ : "+m" (var->value)
+ : "re" (val)
+ : "cc"
+ );
+ AtomicEpilogue();
+#elif defined(VM_ARM_V7)
+ register volatile uint16 res;
+ register volatile uint16 tmp;
+
+ NOT_TESTED();
+
+ dmb();
+
+ __asm__ __volatile__(
+ "1: ldrexh %[tmp], [%[var]] \n\t"
+ "sub %[tmp], %[tmp], %[val] \n\t"
+ "strexh %[res], %[tmp], [%[var]] \n\t"
+ "teq %[res], #0 \n\t"
+ "bne 1b"
+ : [res] "=&r" (res), [tmp] "=&r" (tmp)
+ : [var] "r" (&var->value), [val] "r" (val)
+ : "cc"
+ );
+
+ dmb();
+#elif defined(VM_ARM_64)
+ ARM_64_ATOMIC_16_OPV_PRIVATE_FENCED(var, val, sub);
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Inc16 --
+ *
+ * Atomic read, increment, write.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Inc16(Atomic_uint16 *var) // IN/OUT
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__(
+ "lock; incw %0"
+ : "+m" (var->value)
+ :
+ : "cc"
+ );
+ AtomicEpilogue();
+#elif defined(VM_ARM_ANY)
+ Atomic_Add16(var, 1);
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Dec16 --
+ *
+ * Atomic read, decrement, write.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Dec16(Atomic_uint16 *var) // IN/OUT
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__(
+ "lock; decw %0"
+ : "+m" (var->value)
+ :
+ : "cc"
+ );
+ AtomicEpilogue();
+#elif defined(VM_ARM_ANY)
+ Atomic_Sub16(var, 1);
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadOr16 --
+ *
+ * Atomic read (returned), bitwise OR with a value, write.
+ *
+ * Results:
+ * The value of the variable before the operation.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint16
+Atomic_ReadOr16(Atomic_uint16 *var, // IN/OUT
+ uint16 val) // IN
+{
+ uint16 res;
+
+ do {
+ res = var->value;
+ } while (res != Atomic_ReadIfEqualWrite16(var, res, res | val));
+
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Atomic_ReadAdd16 --
+ *
+ * Atomically adds a 16-bit integer to another
+ *
+ * Results:
+ * Returns the old value just prior to the addition
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE uint16
+Atomic_ReadAdd16(Atomic_uint16 *var, // IN/OUT
+ uint16 val) // IN:
+{
+#if defined(__GNUC__)
+#if (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__(
+ "lock; xaddw %0, %1"
+ : "=r" (val),
+ "+m" (var->value)
+ : "0" (val)
+ : "cc"
+ );
+ AtomicEpilogue();
+ return val;
+#elif defined(VM_ARM_V7)
+ register volatile uint16 res;
+ register volatile uint16 retVal;
+ register volatile uint16 tmp;
+
+ NOT_TESTED();
+
+ dmb();
+
+ __asm__ __volatile__(
+ "1: ldrexh %[retVal], [%[var]] \n\t"
+ "add %[tmp], %[val], %[retVal] \n\t"
+ "strexh %[res], %[tmp], [%[var]] \n\t"
+ "teq %[res], #0 \n\t"
+ "bne 1b"
+ : [tmp] "=&r" (tmp), [res] "=&r" (res), [retVal] "=&r" (retVal)
+ : [var] "r" (&var->value), [val] "r" (val)
+ : "cc"
+ );
+
+ dmb();
+
+ return retVal;
+#elif defined(VM_ARM_64)
+ return ARM_64_ATOMIC_16_OPO_PRIVATE_FENCED(var, val, add);
+#else
+#error No 16-bits atomics.
+#endif
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Atomic_ReadInc16 --
+ *
+ * Atomically increments a 64-bit integer
+ *
+ * Results:
+ * Returns the old value just prior to incrementing
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE uint16
+Atomic_ReadInc16(Atomic_uint16 *var) // IN/OUT
+{
+ return Atomic_ReadAdd16(var, 1);
+}
+
+/*
+
+ *----------------------------------------------------------------------
+ *
+ * Atomic_ReadDec16 --
+ *
+ * Atomically decrements a 64-bit integer
+ *
+ * Results:
+ * Returns the old value just prior to decrementing
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE uint16
+Atomic_ReadDec16(Atomic_uint16 *var) // IN/OUT
+{
+ return Atomic_ReadAdd16(var, -1);
+}
+#endif
+
/*
* Template code for the Atomic_<name> type and its operators.
*
@@ -2607,7 +3841,7 @@ Atomic_TestBit64(Atomic_uint64 *var, // IN
* Atomic_ReadIncInt --
* Atomic_ReadDecInt --
*/
-#if defined(__x86_64__)
+#if defined(VM_64BIT)
MAKE_ATOMIC_TYPE(Ptr, 64, void const *, void *, uintptr_t)
#else
MAKE_ATOMIC_TYPE(Ptr, 32, void const *, void *, uintptr_t)
@@ -2657,6 +3891,6 @@ Atomic_MFence(void)
#ifdef ATOMIC_COMPILER_BARRIER
#undef ATOMIC_COMPILER_BARRIER
-#endif
+#endif /* ATOMIC_COMPILER_BARRIER */
#endif // ifndef _ATOMIC_H_
diff --git a/open-vm-tools/lib/include/vm_basic_asm.h b/open-vm-tools/lib/include/vm_basic_asm.h
index 3f332856..e00109b0 100644
--- a/open-vm-tools/lib/include/vm_basic_asm.h
+++ b/open-vm-tools/lib/include/vm_basic_asm.h
@@ -34,8 +34,6 @@
* vm_basic_asm.h
*
* Basic asm macros
- *
- * ARM not implemented.
*/
#ifndef _VM_BASIC_ASM_H_
@@ -54,229 +52,20 @@
#include "vm_basic_types.h"
#if defined VM_X86_64
+#include "vm_basic_asm_x86_common.h"
#include "vm_basic_asm_x86_64.h"
-#elif defined __i386__
+#elif defined VM_X86_32
+#include "vm_basic_asm_x86_common.h"
#include "vm_basic_asm_x86.h"
+#elif defined VM_ARM_64
+#include "arm64_basic_defs.h"
+#include "vm_basic_asm_arm64.h"
#else
#define MUL64_NO_ASM 1
#include "mul64.h"
#endif
/*
- * x86-64 windows doesn't support inline asm so we have to use these
- * intrinsic functions defined in the compiler. Not all of these are well
- * documented. There is an array in the compiler dll (c1.dll) which has
- * an array of the names of all the intrinsics minus the leading
- * underscore. Searching around in the ntddk.h file can also be helpful.
- *
- * The declarations for the intrinsic functions were taken from the DDK.
- * Our declarations must match the ddk's otherwise the 64-bit c++ compiler
- * will complain about second linkage of the intrinsic functions.
- * We define the intrinsic using the basic types corresponding to the
- * Windows typedefs. This avoids having to include windows header files
- * to get to the windows types.
- */
-#ifdef _MSC_VER
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * It seems x86 & x86-64 windows still implements these intrinsic
- * functions. The documentation for the x86-64 suggest the
- * __inbyte/__outbyte intrinsics even though the _in/_out work fine and
- * __inbyte/__outbyte aren't supported on x86.
- */
-int _inp(unsigned short);
-unsigned short _inpw(unsigned short);
-unsigned long _inpd(unsigned short);
-
-int _outp(unsigned short, int);
-unsigned short _outpw(unsigned short, unsigned short);
-unsigned long _outpd(uint16, unsigned long);
-#pragma intrinsic(_inp, _inpw, _inpd, _outp, _outpw, _outpw, _outpd)
-
-/*
- * Prevents compiler from re-ordering reads, writes and reads&writes.
- * These functions do not add any instructions thus only affect
- * the compiler ordering.
- *
- * See:
- * `Lockless Programming Considerations for Xbox 360 and Microsoft Windows'
- * http://msdn.microsoft.com/en-us/library/bb310595(VS.85).aspx
- */
-void _ReadBarrier(void);
-void _WriteBarrier(void);
-void _ReadWriteBarrier(void);
-#pragma intrinsic(_ReadBarrier, _WriteBarrier, _ReadWriteBarrier)
-
-void _mm_mfence(void);
-void _mm_lfence(void);
-#pragma intrinsic(_mm_mfence, _mm_lfence)
-
-unsigned int __getcallerseflags(void);
-#pragma intrinsic(__getcallerseflags)
-
-#ifdef VM_X86_64
-/*
- * intrinsic functions only supported by x86-64 windows as of 2k3sp1
- */
-unsigned __int64 __rdtsc(void);
-void __stosw(unsigned short *, unsigned short, size_t);
-void __stosd(unsigned long *, unsigned long, size_t);
-void _mm_pause(void);
-#pragma intrinsic(__rdtsc, __stosw, __stosd, _mm_pause)
-
-unsigned char _BitScanForward64(unsigned long *, unsigned __int64);
-unsigned char _BitScanReverse64(unsigned long *, unsigned __int64);
-#pragma intrinsic(_BitScanForward64, _BitScanReverse64)
-#endif /* VM_X86_64 */
-
-unsigned char _BitScanForward(unsigned long *, unsigned long);
-unsigned char _BitScanReverse(unsigned long *, unsigned long);
-#pragma intrinsic(_BitScanForward, _BitScanReverse)
-
-unsigned char _bittest(const long *, long);
-unsigned char _bittestandset(long *, long);
-unsigned char _bittestandreset(long *, long);
-unsigned char _bittestandcomplement(long *, long);
-#pragma intrinsic(_bittest, _bittestandset, _bittestandreset, _bittestandcomplement)
-#ifdef VM_X86_64
-unsigned char _bittestandset64(__int64 *, __int64);
-unsigned char _bittestandreset64(__int64 *, __int64);
-#pragma intrinsic(_bittestandset64, _bittestandreset64)
-#endif /* VM_X86_64 */
-#ifdef __cplusplus
-}
-#endif
-#endif /* _MSC_VER */
-
-
-#ifdef __GNUC__ // {
-#if defined(__i386__) || defined(__x86_64__) // Only on x86*
-
-/*
- * Checked against the Intel manual and GCC --hpreg
- *
- * volatile because reading from port can modify the state of the underlying
- * hardware.
- *
- * Note: The undocumented %z construct doesn't work (internal compiler error)
- * with gcc-2.95.1
- */
-
-#define __GCC_IN(s, type, name) \
-static INLINE type \
-name(uint16 port) \
-{ \
- type val; \
- \
- __asm__ __volatile__( \
- "in" #s " %w1, %0" \
- : "=a" (val) \
- : "Nd" (port) \
- ); \
- \
- return val; \
-}
-
-__GCC_IN(b, uint8, INB)
-__GCC_IN(w, uint16, INW)
-__GCC_IN(l, uint32, IN32)
-
-
-/*
- * Checked against the Intel manual and GCC --hpreg
- *
- * Note: The undocumented %z construct doesn't work (internal compiler error)
- * with gcc-2.95.1
- */
-
-#define __GCC_OUT(s, s2, port, val) do { \
- __asm__( \
- "out" #s " %" #s2 "1, %w0" \
- : \
- : "Nd" (port), "a" (val) \
- ); \
-} while (0)
-
-#define OUTB(port, val) __GCC_OUT(b, b, port, val)
-#define OUTW(port, val) __GCC_OUT(w, w, port, val)
-#define OUT32(port, val) __GCC_OUT(l, , port, val)
-
-#define GET_CURRENT_EIP(_eip) \
- __asm__ __volatile("call 0\n\tpopl %0" : "=r" (_eip): );
-
-static INLINE unsigned int
-GetCallerEFlags(void)
-{
- unsigned long flags;
- asm volatile("pushf; pop %0" : "=r"(flags));
- return flags;
-}
-
-#endif // x86*
-
-#elif defined(_MSC_VER) // } {
-static INLINE uint8
-INB(uint16 port)
-{
- return (uint8)_inp(port);
-}
-static INLINE void
-OUTB(uint16 port, uint8 value)
-{
- _outp(port, value);
-}
-static INLINE uint16
-INW(uint16 port)
-{
- return _inpw(port);
-}
-static INLINE void
-OUTW(uint16 port, uint16 value)
-{
- _outpw(port, value);
-}
-static INLINE uint32
-IN32(uint16 port)
-{
- return _inpd(port);
-}
-static INLINE void
-OUT32(uint16 port, uint32 value)
-{
- _outpd(port, value);
-}
-
-#ifndef VM_X86_64
-#ifdef NEAR
-#undef NEAR
-#endif
-
-#define GET_CURRENT_EIP(_eip) do { \
- __asm call NEAR PTR $+5 \
- __asm pop eax \
- __asm mov _eip, eax \
-} while (0)
-#endif // VM_X86_64
-
-static INLINE unsigned int
-GetCallerEFlags(void)
-{
- return __getcallerseflags();
-}
-
-#else // } {
-#error
-#endif // }
-
-/* Sequence recommended by Intel for the Pentium 4. */
-#define INTEL_MICROCODE_VERSION() ( \
- __SET_MSR(MSR_BIOS_SIGN_ID, 0), \
- __GET_EAX_FROM_CPUID(1), \
- __GET_MSR(MSR_BIOS_SIGN_ID))
-
-/*
* Locate most and least significant bit set functions. Use our own name
* space to avoid namespace collisions. The new names follow a pattern,
* <prefix><size><option>, where:
@@ -305,7 +94,7 @@ GetCallerEFlags(void)
* mssb64 MSB set (uint64) 1..64 0
*/
-#if defined(_MSC_VER)
+#ifdef _MSC_VER
static INLINE int
lssb32_0(const uint32 value)
{
@@ -348,7 +137,7 @@ lssb64_0(const uint64 value)
if (UNLIKELY(value == 0)) {
return -1;
} else {
-#if defined(VM_X86_64)
+#ifdef VM_X86_64
unsigned long idx;
unsigned char ret;
@@ -379,7 +168,7 @@ mssb64_0(const uint64 value)
if (UNLIKELY(value == 0)) {
return -1;
} else {
-#if defined(VM_X86_64)
+#ifdef VM_X86_64
unsigned long idx;
unsigned char ret;
@@ -401,8 +190,9 @@ mssb64_0(const uint64 value)
}
#endif
-#if defined(__GNUC__)
-#if defined(__i386__) || defined(__x86_64__) // Only on x86*
+#ifdef __GNUC__
+
+#ifdef VM_X86_ANY
#define USE_ARCH_X86_CUSTOM
#endif
@@ -438,7 +228,7 @@ mssb64_0(const uint64 value)
static INLINE int
lssb32_0(uint32 value)
{
-#if defined(USE_ARCH_X86_CUSTOM)
+#ifdef USE_ARCH_X86_CUSTOM
if (!__builtin_constant_p(value)) {
if (UNLIKELY(value == 0)) {
return -1;
@@ -465,7 +255,7 @@ mssb32_0(uint32 value)
return -1;
} else {
int pos;
-#if defined(USE_ARCH_X86_CUSTOM)
+#ifdef USE_ARCH_X86_CUSTOM
if (!__builtin_constant_p(value)) {
__asm__ ("bsrl %1, %0\n" : "=r" (pos) : "rm" (value) : "cc");
return pos;
@@ -479,15 +269,15 @@ mssb32_0(uint32 value)
static INLINE int
lssb64_0(const uint64 value)
{
-#if defined(USE_ARCH_X86_CUSTOM)
+#ifdef USE_ARCH_X86_CUSTOM
if (!__builtin_constant_p(value)) {
if (UNLIKELY(value == 0)) {
return -1;
} else {
intptr_t pos;
- #if defined(VM_X86_64)
+#ifdef VM_X86_64
__asm__ ("bsf %1, %0\n" : "=r" (pos) : "rm" (value) : "cc");
- #else
+#else
/* The coding was chosen to minimize conditionals and operations */
pos = lssb32_0((uint32) value);
if (pos == -1) {
@@ -496,7 +286,7 @@ lssb64_0(const uint64 value)
return pos + 32;
}
}
- #endif
+#endif
return pos;
}
}
@@ -505,7 +295,7 @@ lssb64_0(const uint64 value)
}
#endif /* !FEWER_BUILTINS */
-#if defined(FEWER_BUILTINS)
+#ifdef FEWER_BUILTINS
/* GCC 3.3.x does not like __bulitin_clz or __builtin_ffsll. */
static INLINE int
mssb32_0(uint32 value)
@@ -527,9 +317,9 @@ lssb64_0(const uint64 value)
} else {
intptr_t pos;
- #if defined(VM_X86_64)
+#ifdef VM_X86_64
__asm__ __volatile__("bsf %1, %0\n" : "=r" (pos) : "rm" (value) : "cc");
- #else
+#else
/* The coding was chosen to minimize conditionals and operations */
pos = lssb32_0((uint32) value);
if (pos == -1) {
@@ -538,7 +328,7 @@ lssb64_0(const uint64 value)
return pos + 32;
}
}
- #endif /* VM_X86_64 */
+#endif /* VM_X86_64 */
return pos;
}
}
@@ -553,8 +343,8 @@ mssb64_0(const uint64 value)
} else {
intptr_t pos;
-#if defined(USE_ARCH_X86_CUSTOM)
-#if defined(VM_X86_64)
+#ifdef USE_ARCH_X86_CUSTOM
+#ifdef VM_X86_64
__asm__ ("bsr %1, %0\n" : "=r" (pos) : "rm" (value) : "cc");
#else
/* The coding was chosen to minimize conditionals and operations */
@@ -572,16 +362,16 @@ mssb64_0(const uint64 value)
}
}
-#if defined(USE_ARCH_X86_CUSTOM)
+#ifdef USE_ARCH_X86_CUSTOM
#undef USE_ARCH_X86_CUSTOM
#endif
-#endif
+#endif // __GNUC__
static INLINE int
lssbPtr_0(const uintptr_t value)
{
-#if defined(VM_X86_64)
+#ifdef VM_64BIT
return lssb64_0((uint64) value);
#else
return lssb32_0((uint32) value);
@@ -597,7 +387,7 @@ lssbPtr(const uintptr_t value)
static INLINE int
mssbPtr_0(const uintptr_t value)
{
-#if defined(VM_X86_64)
+#ifdef VM_64BIT
return mssb64_0((uint64) value);
#else
return mssb32_0((uint32) value);
@@ -635,7 +425,7 @@ mssb64(const uint64 value)
}
#ifdef __GNUC__
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#if defined(VM_X86_ANY) || defined(VM_ARM_ANY)
/*
*----------------------------------------------------------------------
@@ -656,7 +446,7 @@ mssb64(const uint64 value)
static INLINE void *
uint16set(void *dst, uint16 val, size_t count)
{
-#ifdef __arm__
+#ifdef VM_ARM_32
void *tmpDst = dst;
__asm__ __volatile__ (
@@ -669,7 +459,51 @@ uint16set(void *dst, uint16 val, size_t count)
"2:"
: "+r" (tmpDst), "+r" (count)
: "r" (val)
- : "memory");
+ : "cc", "memory");
+#elif defined(VM_ARM_64)
+ void *tmpDst = dst;
+ uint64 tmpVal = 0;
+
+ if (count == 0) {
+ return dst;
+ }
+
+ __asm__ __volatile__ (
+ "cbz %3, 1f\n\t"
+
+ // Copy 16 bits twice...
+ "bfm %2, %3, #0, #15\n\t"
+ "lsl %2, %2, #16\n\t"
+ "bfm %2, %3, #0, #15\n\t"
+
+ // Copy 32 bits from the bottom of the reg. to the top...
+ "lsl %2, %2, #32\n\t"
+ "bfm %2, %2, #32, #63\n"
+
+ // Copy into dst 8 bytes (4 uint16s) at a time
+ "1:\t"
+ "cmp %1, #4\n\t"
+ "b.lo 2f\n\t"
+ "str %2, [%0], #8\n\t"
+ "sub %1, %1, #4\n\t"
+ "b 1b\n"
+
+ // Copy into dst 4 bytes at a time
+ "2:\t"
+ "cmp %1, #2\n\t"
+ "b.lo 3f\n\t"
+ "str %w2, [%0], #4\n\t"
+ "sub %1, %1, #2\n\t"
+ "b 2b\n"
+
+ // We have 1 or zero items left...
+ "3:\t"
+ "cbz %1, 4f\n\t"
+ "strh %w2, [%0]\n"
+ "4:"
+ : "+r" (tmpDst), "+r" (count), "+r" (tmpVal)
+ : "r" (val)
+ : "cc", "memory");
#else
size_t dummy0;
void *dummy1;
@@ -705,7 +539,7 @@ uint16set(void *dst, uint16 val, size_t count)
static INLINE void *
uint32set(void *dst, uint32 val, size_t count)
{
-#ifdef __arm__
+#ifdef VM_ARM_32
void *tmpDst = dst;
__asm__ __volatile__ (
@@ -718,7 +552,48 @@ uint32set(void *dst, uint32 val, size_t count)
"2:"
: "+r" (tmpDst), "+r" (count)
: "r" (val)
- : "memory");
+ : "cc", "memory");
+#elif defined(VM_ARM_64)
+ void *tmpDst = dst;
+
+ if (count == 0) {
+ return dst;
+ }
+
+ __asm__ __volatile__ (
+ "cbz %2, 1f\n\t"
+
+ // Drop our value in the top 32 bits, then copy from there to the bottom
+ "lsl %2, %2, #32\n\t"
+ "bfm %2, %2, #32, #63\n"
+
+ // Copy four at a time
+ "1:\t"
+ "cmp %1, #16\n\t"
+ "b.lo 2f\n\t"
+ "stp %2, %2, [%0], #16\n\t"
+ "stp %2, %2, [%0], #16\n\t"
+ "stp %2, %2, [%0], #16\n\t"
+ "stp %2, %2, [%0], #16\n\t"
+ "sub %1, %1, #16\n\t"
+ "b 1b\n"
+
+ // Copy remaining pairs of data
+ "2:\t"
+ "cmp %1, #2\n\t"
+ "b.lo 3f\n\t"
+ "str %2, [%0], #8\n\t"
+ "sub %1, %1, #2\n\t"
+ "b 2b\n"
+
+ // One or zero values left to copy
+ "3:\t"
+ "cbz %1, 4f\n\t"
+ "str %w2, [%0]\n\t" // No incr
+ "4:"
+ : "+r" (tmpDst), "+r" (count), "+r" (val)
+ :
+ : "cc", "memory");
#else
size_t dummy0;
void *dummy1;
@@ -754,7 +629,7 @@ uint32set(void *dst, uint32 val, size_t count)
}
return dst;
}
-#endif // defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#endif // defined(VM_X86_ANY) || defined(VM_ARM_ANY)
#elif defined(_MSC_VER)
static INLINE void *
@@ -811,8 +686,15 @@ uint32set(void *dst, uint32 val, size_t count)
static INLINE uint16
Bswap16(uint16 v)
{
+#if defined(VM_ARM_64)
+ __asm__("rev16 %0, %0" : "+r"(v));
+ return v;
+#else
return ((v >> 8) & 0x00ff) | ((v << 8) & 0xff00);
+#endif
}
+
+
/*
*-----------------------------------------------------------------------------
*
@@ -826,12 +708,7 @@ Bswap16(uint16 v)
static INLINE uint32
Bswap32(uint32 v) // IN
{
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) || \
- (defined(__arm__) && !defined(__ANDROID__)) // {
-#ifdef __arm__
- __asm__("rev %0, %0" : "+r"(v));
- return v;
-#else // __arm__
+#if defined(__GNUC__) && defined(VM_X86_ANY)
/* Checked against the Intel manual and GCC. --hpreg */
__asm__(
"bswap %0"
@@ -839,13 +716,18 @@ Bswap32(uint32 v) // IN
: "0" (v)
);
return v;
-#endif // !__arm__
-#else // } {
+#elif defined(VM_ARM_32) && !defined(__ANDROID__)
+ __asm__("rev %0, %0" : "+r"(v));
+ return v;
+#elif defined(VM_ARM_64)
+ __asm__("rev32 %0, %0" : "+r"(v));
+ return v;
+#else
return (v >> 24)
| ((v >> 8) & 0xFF00)
| ((v & 0xFF00) << 8)
| (v << 24) ;
-#endif // }
+#endif
}
#define Bswap Bswap32
@@ -863,17 +745,21 @@ Bswap32(uint32 v) // IN
static INLINE uint64
Bswap64(uint64 v) // IN
{
+#if defined(VM_ARM_64)
+ __asm__("rev %0, %0" : "+r"(v));
+ return v;
+#else
return ((uint64)Bswap((uint32)v) << 32) | Bswap((uint32)(v >> 32));
+#endif
}
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
/*
* COMPILER_MEM_BARRIER prevents the compiler from re-ordering memory
* references accross the barrier. NOTE: It does not generate any
* instruction, so the CPU is free to do whatever it wants to...
*/
-#ifdef __GNUC__ // {
+#ifdef __GNUC__
#define COMPILER_MEM_BARRIER() __asm__ __volatile__ ("": : :"memory")
#define COMPILER_READ_BARRIER() COMPILER_MEM_BARRIER()
#define COMPILER_WRITE_BARRIER() COMPILER_MEM_BARRIER()
@@ -881,7 +767,7 @@ Bswap64(uint64 v) // IN
#define COMPILER_MEM_BARRIER() _ReadWriteBarrier()
#define COMPILER_READ_BARRIER() _ReadBarrier()
#define COMPILER_WRITE_BARRIER() _WriteBarrier()
-#endif // }
+#endif
/*
@@ -934,7 +820,7 @@ static INLINE void
PAUSE(void)
#ifdef __GNUC__
{
-#if defined(__arm__)
+#ifdef VM_ARM_ANY
/*
* ARM has no instruction to execute "spin-wait loop", just leave it
* empty.
@@ -979,7 +865,7 @@ RDTSC(void)
);
return tscHigh << 32 | tscLow;
-#elif defined(__i386__)
+#elif defined(VM_X86_32)
uint64 tim;
__asm__ __volatile__(
@@ -988,6 +874,12 @@ RDTSC(void)
);
return tim;
+#elif defined(VM_ARM_64)
+#if (defined(VMKERNEL) || defined(VMM)) && !defined(VMK_ARM_EL1)
+ return MRS(CNTPCT_EL0);
+#else
+ return MRS(CNTVCT_EL0);
+#endif
#else
/*
* For platform without cheap timer, just return 0.
@@ -1011,77 +903,27 @@ RDTSC(void)
#error No compiler defined for RDTSC
#endif /* __GNUC__ */
-#if defined(__i386__) || defined(__x86_64__)
-/*
- *-----------------------------------------------------------------------------
- *
- * RDTSC_BARRIER --
- *
- * Implements an RDTSC fence. Instructions executed prior to the
- * fence will have completed before the fence and all stores to
- * memory are flushed from the store buffer.
- *
- * On AMD, MFENCE is sufficient. On Intel, only LFENCE is
- * documented to fence RDTSC, but LFENCE won't drain the store
- * buffer. So, use MFENCE;LFENCE, which will work on both AMD and
- * Intel.
- *
- * It is the callers' responsibility to check for SSE2 before
- * calling this function.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Cause loads and stores prior to this to be globally visible, and
- * RDTSC will not pass.
- *
- *-----------------------------------------------------------------------------
- */
-
-static INLINE void
-RDTSC_BARRIER(void)
-{
-#ifdef __GNUC__
- __asm__ __volatile__(
- "mfence \n\t"
- "lfence \n\t"
- ::: "memory"
- );
-#elif defined _MSC_VER
- /* Prevent compiler from moving code across mfence/lfence. */
- _ReadWriteBarrier();
- _mm_mfence();
- _mm_lfence();
- _ReadWriteBarrier();
-#else
-#error No compiler defined for RDTSC_BARRIER
-#endif
-}
-
-#endif // __i386 || __x86_64__
/*
*-----------------------------------------------------------------------------
*
* DEBUGBREAK --
*
- * Does an int3 for MSVC / GCC. This is a macro to make sure int3 is
- * always inlined.
+ * Does an int3 for MSVC / GCC, bkpt/brk for ARM. This is a macro to make
+ * sure int3 is always inlined.
*
*-----------------------------------------------------------------------------
*/
-#ifdef __arm__
+#ifdef VM_ARM_32
#define DEBUGBREAK() __asm__("bkpt")
-#else
-#ifdef _MSC_VER
+#elif defined(VM_ARM_64)
+#define DEBUGBREAK() __asm__("brk #0")
+#elif defined(_MSC_VER)
#define DEBUGBREAK() __debugbreak()
#else
#define DEBUGBREAK() __asm__("int $3")
#endif
-#endif // __arm__
-#endif // defined(__i386__) || defined(__x86_64__) || defined(__arm__)
/*
@@ -1090,12 +932,14 @@ RDTSC_BARRIER(void)
* {Clear,Set,Test}Bit{32,64} --
*
* Sets or clears a specified single bit in the provided variable.
+ *
* The index input value specifies which bit to modify and is 0-based.
* Index is truncated by hardware to a 5-bit or 6-bit offset for the
* 32 and 64-bit flavors, respectively, but input values are not validated
* with asserts to avoid include dependencies.
- * 64-bit flavors are not provided for 32-bit builds because the inlined
- * version can defeat user or compiler optimizations.
+ *
+ * 64-bit flavors are not handcrafted for 32-bit builds because they may
+ * defeat compiler optimizations.
*
*-----------------------------------------------------------------------------
*/
@@ -1103,7 +947,7 @@ RDTSC_BARRIER(void)
static INLINE void
SetBit32(uint32 *var, uint32 index)
{
-#ifdef __GNUC__
+#if defined(__GNUC__) && defined(VM_X86_ANY)
__asm__ (
"bts %1, %0"
: "+mr" (*var)
@@ -1112,13 +956,15 @@ SetBit32(uint32 *var, uint32 index)
);
#elif defined(_MSC_VER)
_bittestandset((long *)var, index);
+#else
+ *var |= (1 << index);
#endif
}
static INLINE void
ClearBit32(uint32 *var, uint32 index)
{
-#ifdef __GNUC__
+#if defined(__GNUC__) && defined(VM_X86_ANY)
__asm__ (
"btr %1, %0"
: "+mr" (*var)
@@ -1127,13 +973,15 @@ ClearBit32(uint32 *var, uint32 index)
);
#elif defined(_MSC_VER)
_bittestandreset((long *)var, index);
+#else
+ *var &= ~(1 << index);
#endif
}
-#if defined(VM_X86_64)
static INLINE void
SetBit64(uint64 *var, uint64 index)
{
+#if defined(VM_64BIT) && !defined(VM_ARM_64)
#ifdef __GNUC__
__asm__ (
"bts %1, %0"
@@ -1141,14 +989,18 @@ SetBit64(uint64 *var, uint64 index)
: "rJ" (index)
: "cc"
);
-#elif defined _MSC_VER
+#elif defined(_MSC_VER)
_bittestandset64((__int64 *)var, index);
#endif
+#else
+ *var |= ((uint64)1 << index);
+#endif
}
static INLINE void
ClearBit64(uint64 *var, uint64 index)
{
+#if defined(VM_64BIT) && !defined(VM_ARM_64)
#ifdef __GNUC__
__asm__ (
"btrq %1, %0"
@@ -1156,16 +1008,18 @@ ClearBit64(uint64 *var, uint64 index)
: "rJ" (index)
: "cc"
);
-#elif defined _MSC_VER
+#elif defined(_MSC_VER)
_bittestandreset64((__int64 *)var, index);
#endif
+#else
+ *var &= ~((uint64)1 << index);
+#endif
}
-#endif /* VM_X86_64 */
static INLINE Bool
TestBit32(const uint32 *var, uint32 index)
{
-#ifdef __GNUC__
+#if defined(__GNUC__) && defined(VM_X86_ANY)
Bool bit;
__asm__ (
"bt %[index], %[var] \n"
@@ -1216,12 +1070,12 @@ TestBit64(const uint64 *var, uint64 index)
static INLINE Bool
SetBitVector(void *var, int32 index)
{
-#ifdef __GNUC__
+#if defined(__GNUC__) && defined(VM_X86_ANY)
Bool bit;
__asm__ (
"bts %2, %1;"
"setc %0"
- : "=qQm" (bit), "+m" (*(volatile uint32 *)var)
+ : "=qQm" (bit), "+m" (*(uint32 *)var)
: "rI" (index)
: "memory", "cc"
);
@@ -1229,19 +1083,21 @@ SetBitVector(void *var, int32 index)
#elif defined(_MSC_VER)
return _bittestandset((long *)var, index) != 0;
#else
-#error No compiler defined for SetBitVector
+ Bool retVal = (((uint8 *)var)[index / 8] & (1 << (index % 8))) != 0;
+ ((uint8 *)var)[index / 8] |= 1 << (index % 8);
+ return retVal;
#endif
}
static INLINE Bool
ClearBitVector(void *var, int32 index)
{
-#ifdef __GNUC__
+#if defined(__GNUC__) && defined(VM_X86_ANY)
Bool bit;
__asm__ (
"btr %2, %1;"
"setc %0"
- : "=qQm" (bit), "+m" (*(volatile uint32 *)var)
+ : "=qQm" (bit), "+m" (*(uint32 *)var)
: "rI" (index)
: "cc"
);
@@ -1249,19 +1105,21 @@ ClearBitVector(void *var, int32 index)
#elif defined(_MSC_VER)
return _bittestandreset((long *)var, index) != 0;
#else
-#error No compiler defined for ClearBitVector
+ Bool retVal = (((uint8 *)var)[index / 8] & (1 << (index % 8))) != 0;
+ ((uint8 *)var)[index / 8] &= ~(1 << (index % 8));
+ return retVal;
#endif
}
static INLINE Bool
ComplementBitVector(void *var, int32 index)
{
-#ifdef __GNUC__
+#if defined(__GNUC__) && defined(VM_X86_ANY)
Bool bit;
__asm__ (
"btc %2, %1;"
"setc %0"
- : "=qQm" (bit), "+m" (*(volatile uint32 *)var)
+ : "=qQm" (bit), "+m" (*(uint32 *)var)
: "rI" (index)
: "cc"
);
@@ -1269,14 +1127,16 @@ ComplementBitVector(void *var, int32 index)
#elif defined(_MSC_VER)
return _bittestandcomplement((long *)var, index) != 0;
#else
-#error No compiler defined for ComplementBitVector
+ Bool retVal = (((uint8 *)var)[index / 8] & (1 << (index % 8))) != 0;
+ ((uint8 *)var)[index / 8] ^= ~(1 << (index % 8));
+ return retVal;
#endif
}
static INLINE Bool
TestBitVector(const void *var, int32 index)
{
-#ifdef __GNUC__
+#if defined(__GNUC__) && defined(VM_X86_ANY)
Bool bit;
__asm__ (
"bt %2, %1;"
@@ -1289,7 +1149,7 @@ TestBitVector(const void *var, int32 index)
#elif defined _MSC_VER
return _bittest((long *)var, index) != 0;
#else
-#error No compiler defined for TestBitVector
+ return (((const uint8 *)var)[index / 8] & (1 << (index % 8))) != 0;
#endif
}
@@ -1314,7 +1174,7 @@ RoundUpPow2C64(uint64 value)
}
}
-#if defined(VM_X86_64) && defined(__GNUC__)
+#if defined(__GNUC__) && defined(VM_X86_64)
static INLINE uint64
RoundUpPow2Asm64(uint64 value)
{
@@ -1336,7 +1196,7 @@ RoundUpPow2Asm64(uint64 value)
static INLINE uint64
RoundUpPow2_64(uint64 value)
{
-#if defined(VM_X86_64) && defined(__GNUC__)
+#if defined(__GNUC__) && defined(VM_X86_64)
if (__builtin_constant_p(value)) {
return RoundUpPow2C64(value);
} else {
@@ -1361,7 +1221,7 @@ RoundUpPow2C32(uint32 value)
static INLINE uint32
RoundUpPow2Asm32(uint32 value)
{
-#ifdef __arm__
+#ifdef VM_ARM_32
uint32 out = 1;
// Note: None Thumb only!
// The value of the argument "value"
@@ -1374,6 +1234,8 @@ RoundUpPow2Asm32(uint32 value)
// if out == 2^32 then out = 1 as it is right rotate
: [in]"+r"(value),[out]"+r"(out));
return out;
+#elif defined(VM_ARM_64)
+ return RoundUpPow2C32(value);
#else
uint32 out = 2;
diff --git a/open-vm-tools/lib/include/vm_basic_asm_x86.h b/open-vm-tools/lib/include/vm_basic_asm_x86.h
index 49b617a7..745c483b 100644
--- a/open-vm-tools/lib/include/vm_basic_asm_x86.h
+++ b/open-vm-tools/lib/include/vm_basic_asm_x86.h
@@ -559,5 +559,4 @@ Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
#pragma warning(default: 4035)
#endif
-
#endif
diff --git a/open-vm-tools/lib/include/vm_basic_asm_x86_64.h b/open-vm-tools/lib/include/vm_basic_asm_x86_64.h
index ecb4189f..cc882ada 100644
--- a/open-vm-tools/lib/include/vm_basic_asm_x86_64.h
+++ b/open-vm-tools/lib/include/vm_basic_asm_x86_64.h
@@ -89,18 +89,22 @@ uint64 __shiftright128(uint64 lowPart, uint64 highPart, uint8 shift);
__rip; \
})
+#define GET_CURRENT_PC() GET_CURRENT_RIP()
+
/*
* GET_CURRENT_LOCATION
*
* Updates the arguments with the values of the %rip, %rbp, and %rsp
- * registers at the current code location where the macro is invoked.
+ * registers at the current code location where the macro is invoked,
+ * and the return address.
*/
-#define GET_CURRENT_LOCATION(rip, rbp, rsp) \
- asm("lea 0(%%rip), %0\n" \
- "mov %%rbp, %1\n" \
- "mov %%rsp, %2\n" \
- : "=r" (rip), "=r" (rbp), "=r" (rsp))
-
+#define GET_CURRENT_LOCATION(rip, rbp, rsp, retAddr) do { \
+ asm("lea 0(%%rip), %0\n" \
+ "mov %%rbp, %1\n" \
+ "mov %%rsp, %2\n" \
+ : "=r" (rip), "=r" (rbp), "=r" (rsp)); \
+ retAddr = (uint64) GetReturnAddress(); \
+ } while (0)
#endif
/*
diff --git a/open-vm-tools/lib/include/vm_basic_asm_x86_common.h b/open-vm-tools/lib/include/vm_basic_asm_x86_common.h
new file mode 100644
index 00000000..bcf51a04
--- /dev/null
+++ b/open-vm-tools/lib/include/vm_basic_asm_x86_common.h
@@ -0,0 +1,327 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*********************************************************
+ * The contents of this file are subject to the terms of the Common
+ * Development and Distribution License (the "License") version 1.0
+ * and no later version. You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ * http://www.opensource.org/licenses/cddl1.php
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ *********************************************************/
+
+/*
+ * vm_basic_asm_x86_common.h --
+ *
+ * Basic assembler macros common to 32-bit and 64-bit x86 ISA.
+ */
+
+#ifndef _VM_BASIC_ASM_X86_COMMON_H_
+#define _VM_BASIC_ASM_X86_COMMON_H_
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_VMK_MODULE
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_DISTRIBUTE
+#define INCLUDE_ALLOW_VMCORE
+#include "includeCheck.h"
+
+#ifndef VM_X86_ANY
+#error "Should be included only in x86 builds"
+#endif
+
+/*
+ * x86-64 windows doesn't support inline asm so we have to use these
+ * intrinsic functions defined in the compiler. Not all of these are well
+ * documented. There is an array in the compiler dll (c1.dll) which has
+ * an array of the names of all the intrinsics minus the leading
+ * underscore. Searching around in the ntddk.h file can also be helpful.
+ *
+ * The declarations for the intrinsic functions were taken from the DDK.
+ * Our declarations must match the ddk's otherwise the 64-bit c++ compiler
+ * will complain about second linkage of the intrinsic functions.
+ * We define the intrinsic using the basic types corresponding to the
+ * Windows typedefs. This avoids having to include windows header files
+ * to get to the windows types.
+ */
+#if defined(_MSC_VER) && !defined(BORA_NO_WIN32_INTRINS)
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * It seems x86 & x86-64 windows still implements these intrinsic
+ * functions. The documentation for the x86-64 suggest the
+ * __inbyte/__outbyte intrinsics even though the _in/_out work fine and
+ * __inbyte/__outbyte aren't supported on x86.
+ */
+int _inp(unsigned short);
+unsigned short _inpw(unsigned short);
+unsigned long _inpd(unsigned short);
+
+int _outp(unsigned short, int);
+unsigned short _outpw(unsigned short, unsigned short);
+unsigned long _outpd(uint16, unsigned long);
+#pragma intrinsic(_inp, _inpw, _inpd, _outp, _outpw, _outpw, _outpd)
+
+/*
+ * Prevents compiler from re-ordering reads, writes and reads&writes.
+ * These functions do not add any instructions thus only affect
+ * the compiler ordering.
+ *
+ * See:
+ * `Lockless Programming Considerations for Xbox 360 and Microsoft Windows'
+ * http://msdn.microsoft.com/en-us/library/bb310595(VS.85).aspx
+ */
+void _ReadBarrier(void);
+void _WriteBarrier(void);
+void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadBarrier, _WriteBarrier, _ReadWriteBarrier)
+
+void _mm_mfence(void);
+void _mm_lfence(void);
+#pragma intrinsic(_mm_mfence, _mm_lfence)
+
+unsigned int __getcallerseflags(void);
+#pragma intrinsic(__getcallerseflags)
+
+#ifdef VM_X86_64
+/*
+ * intrinsic functions only supported by x86-64 windows as of 2k3sp1
+ */
+unsigned __int64 __rdtsc(void);
+void __stosw(unsigned short *, unsigned short, size_t);
+void __stosd(unsigned long *, unsigned long, size_t);
+void _mm_pause(void);
+#pragma intrinsic(__rdtsc, __stosw, __stosd, _mm_pause)
+
+unsigned char _BitScanForward64(unsigned long *, unsigned __int64);
+unsigned char _BitScanReverse64(unsigned long *, unsigned __int64);
+#pragma intrinsic(_BitScanForward64, _BitScanReverse64)
+#endif /* VM_X86_64 */
+
+unsigned char _BitScanForward(unsigned long *, unsigned long);
+unsigned char _BitScanReverse(unsigned long *, unsigned long);
+#pragma intrinsic(_BitScanForward, _BitScanReverse)
+
+unsigned char _bittest(const long *, long);
+unsigned char _bittestandset(long *, long);
+unsigned char _bittestandreset(long *, long);
+unsigned char _bittestandcomplement(long *, long);
+#pragma intrinsic(_bittest, _bittestandset, _bittestandreset, _bittestandcomplement)
+#ifdef VM_X86_64
+unsigned char _bittestandset64(__int64 *, __int64);
+unsigned char _bittestandreset64(__int64 *, __int64);
+#pragma intrinsic(_bittestandset64, _bittestandreset64)
+#endif // VM_X86_64
+#ifdef __cplusplus
+}
+#endif
+#endif // _MSC_VER
+
+#ifdef __GNUC__
+/*
+ * Checked against the Intel manual and GCC --hpreg
+ *
+ * volatile because reading from port can modify the state of the underlying
+ * hardware.
+ *
+ * Note: The undocumented %z construct doesn't work (internal compiler error)
+ * with gcc-2.95.1
+ */
+
+#define __GCC_IN(s, type, name) \
+static INLINE type \
+name(uint16 port) \
+{ \
+ type val; \
+ \
+ __asm__ __volatile__( \
+ "in" #s " %w1, %0" \
+ : "=a" (val) \
+ : "Nd" (port) \
+ ); \
+ \
+ return val; \
+}
+
+__GCC_IN(b, uint8, INB)
+__GCC_IN(w, uint16, INW)
+__GCC_IN(l, uint32, IN32)
+
+
+/*
+ * Checked against the Intel manual and GCC --hpreg
+ *
+ * Note: The undocumented %z construct doesn't work (internal compiler error)
+ * with gcc-2.95.1
+ */
+
+#define __GCC_OUT(s, s2, port, val) do { \
+ __asm__( \
+ "out" #s " %" #s2 "1, %w0" \
+ : \
+ : "Nd" (port), "a" (val) \
+ ); \
+} while (0)
+
+#define OUTB(port, val) __GCC_OUT(b, b, port, val)
+#define OUTW(port, val) __GCC_OUT(w, w, port, val)
+#define OUT32(port, val) __GCC_OUT(l, , port, val)
+
+#define GET_CURRENT_EIP(_eip) \
+ __asm__ __volatile("call 0\n\tpopl %0" : "=r" (_eip): );
+
+static INLINE unsigned int
+GetCallerEFlags(void)
+{
+ unsigned long flags;
+ asm volatile("pushf; pop %0" : "=r"(flags));
+ return flags;
+}
+
+#elif defined(_MSC_VER)
+static INLINE uint8
+INB(uint16 port)
+{
+ return (uint8)_inp(port);
+}
+static INLINE void
+OUTB(uint16 port, uint8 value)
+{
+ _outp(port, value);
+}
+static INLINE uint16
+INW(uint16 port)
+{
+ return _inpw(port);
+}
+static INLINE void
+OUTW(uint16 port, uint16 value)
+{
+ _outpw(port, value);
+}
+static INLINE uint32
+IN32(uint16 port)
+{
+ return _inpd(port);
+}
+static INLINE void
+OUT32(uint16 port, uint32 value)
+{
+ _outpd(port, value);
+}
+
+#ifndef VM_X86_64
+#ifdef NEAR
+#undef NEAR
+#endif
+
+#define GET_CURRENT_EIP(_eip) do { \
+ __asm call NEAR PTR $+5 \
+ __asm pop eax \
+ __asm mov _eip, eax \
+} while (0)
+#endif // VM_X86_64
+
+static INLINE unsigned int
+GetCallerEFlags(void)
+{
+ return __getcallerseflags();
+}
+
+#endif // __GNUC__
+
+/* Sequence recommended by Intel for the Pentium 4. */
+#define INTEL_MICROCODE_VERSION() ( \
+ __SET_MSR(MSR_BIOS_SIGN_ID, 0), \
+ __GET_EAX_FROM_CPUID(1), \
+ __GET_MSR(MSR_BIOS_SIGN_ID))
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * RDTSC_BARRIER --
+ *
+ * Implements an RDTSC fence. Instructions executed prior to the
+ * fence will have completed before the fence and all stores to
+ * memory are flushed from the store buffer.
+ *
+ * On AMD, MFENCE is sufficient. On Intel, only LFENCE is
+ * documented to fence RDTSC, but LFENCE won't drain the store
+ * buffer. So, use MFENCE;LFENCE, which will work on both AMD and
+ * Intel.
+ *
+ * It is the callers' responsibility to check for SSE2 before
+ * calling this function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Cause loads and stores prior to this to be globally visible, and
+ * RDTSC will not pass.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+RDTSC_BARRIER(void)
+{
+#ifdef __GNUC__
+ __asm__ __volatile__(
+ "mfence \n\t"
+ "lfence \n\t"
+ ::: "memory"
+ );
+#elif defined _MSC_VER
+ /* Prevent compiler from moving code across mfence/lfence. */
+ _ReadWriteBarrier();
+ _mm_mfence();
+ _mm_lfence();
+ _ReadWriteBarrier();
+#else
+#error No compiler defined for RDTSC_BARRIER
+#endif
+}
+
+
+/*
+ * Compiler/CPU barriers. These take the form of <mem access type>_<mem access
+ * type>_MEM_BARRIER, where <mem access type> is either LD (load), ST (store) or
+ * LDST (any). On x86 we only need to care specifically about store-load
+ * reordering on normal memory types and mfence, otherwise only a compiler
+ * barrier is needed.
+ */
+#define LD_LD_MEM_BARRIER() COMPILER_MEM_BARRIER()
+#define LD_ST_MEM_BARRIER() COMPILER_MEM_BARRIER()
+#define LD_LDST_MEM_BARRIER() COMPILER_MEM_BARRIER()
+#define ST_LD_MEM_BARRIER() asm volatile ("mfence" ::: "memory")
+#define ST_ST_MEM_BARRIER() COMPILER_MEM_BARRIER()
+#define ST_LDST_MEM_BARRIER() ST_LD_MEM_BARRIER()
+#define LDST_LD_MEM_BARRIER() ST_LD_MEM_BARRIER()
+#define LDST_ST_MEM_BARRIER() COMPILER_MEM_BARRIER()
+#define LDST_LDST_MEM_BARRIER() ST_LD_MEM_BARRIER()
+
+#endif // _VM_BASIC_ASM_X86_COMMON_H_
diff --git a/open-vm-tools/lib/include/vm_basic_defs.h b/open-vm-tools/lib/include/vm_basic_defs.h
index 01006e6b..81c5e218 100644
--- a/open-vm-tools/lib/include/vm_basic_defs.h
+++ b/open-vm-tools/lib/include/vm_basic_defs.h
@@ -93,30 +93,40 @@
* Simple macros
*/
+#ifndef vmw_offsetof
+#define vmw_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
#if (defined __APPLE__ || defined __FreeBSD__) && \
(!defined KERNEL && !defined _KERNEL && !defined VMKERNEL && !defined __KERNEL__)
# include <stddef.h>
#else
-// XXX the _WIN32 one matches that of VC++, to prevent redefinition warning
-// XXX the other one matches that of gcc3.3.3/glibc2.2.4 to prevent redefinition warnings
#ifndef offsetof
#define VMW_DEFINED_OFFSETOF
-#ifdef _WIN32
-#define offsetof(s,m) (size_t)&(((s *)0)->m)
-#else
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#endif
-#endif
-#endif // __APPLE__
/*
+ * XXX While the _WIN32 implementation appears to be identical to vmw_offsetof
+ * in terms of behavior, they need to be separate to match verbatim the
+ * definition used by the respective compilers, to avoid a redefinition warning.
+ *
* This is necessary until we eliminate the inclusion of <windows.h> above.
- * At that time, it should be possible to use "offsetof" everywhere.
*/
-#ifndef vmw_offsetof
-#define vmw_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#ifdef _WIN32
+#define offsetof(s,m) (size_t)&(((s *)0)->m)
+/*
+ * We use the builtin offset for gcc/clang, except when we're running under the
+ * vmkernel's GDB macro preprocessor, since gdb doesn't understand
+ * __builtin_offsetof.
+ */
+#elif defined __GNUC__ && !defined VMKERNEL_GDB_MACRO_BUILDER
+#define offsetof __builtin_offsetof
+#else
+#define offsetof vmw_offsetof
#endif
+#endif // offsetof
+#endif // __APPLE__
+
#define VMW_CONTAINER_OF(ptr, type, member) \
((type *)((char *)(ptr) - vmw_offsetof(type, member)))
@@ -238,6 +248,8 @@ Max(int a, int b)
#define PAGE_SHIFT 12
#elif defined __APPLE__
#define PAGE_SHIFT 12
+#elif defined VM_ARM_64
+ #define PAGE_SHIFT 12
#elif defined __arm__
#define PAGE_SHIFT 12
#else
@@ -246,7 +258,7 @@ Max(int a, int b)
#endif // }
#ifndef PAGE_SIZE
-#define PAGE_SIZE (1<<PAGE_SHIFT)
+#define PAGE_SIZE (1 << PAGE_SHIFT)
#endif
#ifndef PAGE_MASK
@@ -254,11 +266,15 @@ Max(int a, int b)
#endif
#ifndef PAGE_OFFSET
-#define PAGE_OFFSET(_addr) ((uintptr_t)(_addr)&(PAGE_SIZE-1))
+#define PAGE_OFFSET(_addr) ((uintptr_t)(_addr) & (PAGE_SIZE - 1))
+#endif
+
+#ifndef PAGE_NUMBER
+#define PAGE_NUMBER(_addr) ((uintptr_t)(_addr) / PAGE_SIZE)
#endif
#ifndef VM_PAGE_BASE
-#define VM_PAGE_BASE(_addr) ((_addr)&~(PAGE_SIZE-1))
+#define VM_PAGE_BASE(_addr) ((_addr) & ~(PAGE_SIZE - 1))
#endif
#ifndef VM_PAGES_SPANNED
@@ -340,8 +356,12 @@ Max(int a, int b)
#define HIBYTE(_w) (((_w) >> 8) & 0xff)
#endif
+#ifndef HIDWORD
#define HIDWORD(_qw) ((uint32)((_qw) >> 32))
+#endif
+#ifndef LODWORD
#define LODWORD(_qw) ((uint32)(_qw))
+#endif
#define QWORD(_hi, _lo) ((((uint64)(_hi)) << 32) | ((uint32)(_lo)))
@@ -556,9 +576,31 @@ typedef int pid_t;
#endif
/*
+ * Convenience definitions of unicode characters.
+ */
+
+#ifndef UTF8_ELLIPSIS
+#define UTF8_ELLIPSIS "\xe2\x80\xa6"
+#endif
+
+/*
* Convenience macros and definitions. Can often be used instead of #ifdef.
*/
+#undef ARM64_ONLY
+#ifdef VM_ARM_64
+#define ARM64_ONLY(x) x
+#else
+#define ARM64_ONLY(x)
+#endif
+
+#undef X86_ONLY
+#ifdef VM_X86_ANY
+#define X86_ONLY(x) x
+#else
+#define X86_ONLY(x)
+#endif
+
#undef DEBUG_ONLY
#ifdef VMX86_DEBUG
#define vmx86_debug 1
@@ -753,9 +795,31 @@ typedef int pid_t;
/*
* Typical cache line size. Use this for aligning structures to cache
* lines for performance, but do not rely on it for correctness.
+ *
+ * On x86, all current processors newer than P4 have 64-byte lines,
+ * but P4 had 128.
+ *
+ * On ARM, the line size can vary between cores. 64-byte lines are
+ * common, but either larger or smaller powers of two are possible.
*/
#define CACHELINE_SIZE 64
+#define CACHELINE_SHIFT 6
#define CACHELINE_ALIGNMENT_MASK (CACHELINE_SIZE - 1)
+/*
+ * Bits to bytes sizes.
+ */
+
+#define SIZE_8BIT 1
+#define SIZE_16BIT 2
+#define SIZE_24BIT 3
+#define SIZE_32BIT 4
+#define SIZE_48BIT 6
+#define SIZE_64BIT 8
+#define SIZE_80BIT 10
+#define SIZE_128BIT 16
+#define SIZE_256BIT 32
+
+
#endif // ifndef _VM_BASIC_DEFS_H_
diff --git a/open-vm-tools/lib/include/vm_basic_math.h b/open-vm-tools/lib/include/vm_basic_math.h
index 470071bb..862f21f4 100644
--- a/open-vm-tools/lib/include/vm_basic_math.h
+++ b/open-vm-tools/lib/include/vm_basic_math.h
@@ -80,4 +80,87 @@ GetPowerOfTwo(uint32 x)
return power2;
}
+
+#if !defined(_WIN32) && !defined(_WIN64)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * RotateLeft32 --
+ *
+ * Results:
+ * Value rotated to the left by 'shift' bits.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static INLINE uint32
+RotateLeft32(uint32 value, uint8 shift)
+{
+ return ((value << shift) | (value >> (32 - shift)));
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * RotateRight32 --
+ *
+ * Results:
+ * Value rotated to the right by 'shift' bits.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static INLINE uint32
+RotateRight32(uint32 value, uint8 shift)
+{
+ return ((value >> shift) | (value << (32 - shift)));
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * RotateLeft64 --
+ *
+ * Results:
+ * Value rotated to the left by 'shift' bits.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static INLINE uint64
+RotateLeft64(uint64 value, uint8 shift)
+{
+ return ((value << shift) | (value >> (64 - shift)));
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * RotateRight64 --
+ *
+ * Results:
+ * Value rotated to the right by 'shift' bits.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static INLINE uint64
+RotateRight64(uint64 value, uint8 shift)
+{
+ return ((value >> shift) | (value << (64 - shift)));
+}
+#endif // if !defined(_WIN32) && !defined(_WIN64)
+
+
#endif // ifndef _VM_BASIC_MATH_H_
diff --git a/open-vm-tools/lib/include/vm_basic_types.h b/open-vm-tools/lib/include/vm_basic_types.h
index 4af1500a..f5e639f6 100644
--- a/open-vm-tools/lib/include/vm_basic_types.h
+++ b/open-vm-tools/lib/include/vm_basic_types.h
@@ -104,18 +104,63 @@ typedef char Bool;
# define __i386__
#endif
+/*
+ * Setup a bunch of defines for instruction set architecture (ISA) related
+ * properties.
+ *
+ * For compiler types/size:
+ *
+ * - VM_32BIT for a 32-bit ISA (with the same C compiler types/sizes as 32-bit
+ * x86/ARM).
+ * - VM_64BIT for a 64-bit ISA (with the same C compiler types/sizes as 64-bit
+ * x86/ARM).
+ *
+ * For a given <arch> in {X86, ARM}:
+ *
+ * - VM_<arch>_32 for the 32-bit variant.
+ * - VM_<arch>_64 for the 64-bit variant.
+ * - VM_<arch>_ANY for any variant of <arch>.
+ *
+ * VM_X86_ANY is synonymous with the confusing and deprecated VM_I386 (which
+ * should really be VM_X86_32).
+ */
+
#ifdef __i386__
+/* VM_I386 is historically synonymous with VM_X86_ANY in bora, but misleading,
+ * since it is confused with the __i386__ gcc but defined for both 32- and
+ * 64-bit x86. We retain it here for legacy compatibility.
+ */
#define VM_I386
+#define VM_X86_32
+#define VM_X86_ANY
+#define VM_32BIT
#endif
#ifdef __x86_64__
#define VM_X86_64
#define VM_I386
+#define VM_X86_ANY
+#define VM_64BIT
#define vm_x86_64 (1)
#else
#define vm_x86_64 (0)
#endif
+#ifdef __arm__
+#define VM_ARM_32
+#define VM_ARM_ANY
+#define VM_32BIT
+#endif
+
+#ifdef __aarch64__
+#define VM_ARM_64
+#define VM_ARM_ANY
+#define VM_64BIT
+#define vm_arm_64 (1)
+#else
+#define vm_arm_64 (0)
+#endif
+
#ifdef _MSC_VER
#pragma warning (3 :4505) // unreferenced local function
@@ -129,7 +174,31 @@ typedef char Bool;
#endif
-#if defined(__APPLE__) || defined(HAVE_STDINT_H)
+#if defined(__linux__) && defined(__cplusplus) && __cplusplus >= 201103L
+
+/*
+ * We're using stdint.h instead of cstdint below because of libstdcpp.cpp.
+ * It looks like a C++ file. When being preprocessed all the C++ specific
+ * defines(e.g. __cplusplus) are set, but the C++ include paths are not.
+ */
+#include <stdint.h>
+
+typedef char Bool;
+
+typedef uint64_t uint64;
+typedef int64_t int64;
+typedef uint32_t uint32;
+typedef int32_t int32;
+typedef uint16_t uint16;
+typedef int16_t int16;
+typedef uint8_t uint8;
+typedef int8_t int8;
+
+typedef uint64 BA;
+typedef uint64 MA;
+typedef uint32 MPN32;
+
+#elif defined(__APPLE__) || defined(HAVE_STDINT_H)
/*
* TODO: This is a C99 standard header. We should be able to test for
@@ -168,7 +237,7 @@ typedef signed __int64 int64;
#elif __GNUC__
/* The Xserver source compiles with -ansi -pendantic */
# if !defined(__STRICT_ANSI__) || defined(__FreeBSD__)
-# if defined(VM_X86_64)
+# if defined(VM_X86_64) || defined(VM_ARM_64)
typedef unsigned long uint64;
typedef long int64;
# else
@@ -256,6 +325,9 @@ typedef int64 intptr_t;
# else
typedef int32 intptr_t;
# endif
+# elif defined(VM_ARM_64)
+# define __intptr_t_defined
+typedef int64 intptr_t;
# elif defined(__arm__)
# define __intptr_t_defined
typedef int32 intptr_t;
@@ -269,6 +341,8 @@ typedef uint64 uintptr_t;
# else
typedef uint32 uintptr_t;
# endif
+# elif defined(VM_ARM_64)
+typedef uint64 uintptr_t;
# elif defined(__arm__)
typedef uint32 uintptr_t;
# endif
@@ -289,7 +363,8 @@ typedef int64 VmTimeVirtualClock; /* Virtual Clock kept in CPU cycles */
/*
* Printf format specifiers for size_t and 64-bit number.
* Use them like this:
- * printf("%"FMT64"d\n", big);
+ * printf("%" FMT64 "d\n", big);
+ * The spaces are important for C++11 compatibility.
*
* FMTH is for handles/fds.
*/
@@ -325,7 +400,7 @@ typedef int64 VmTimeVirtualClock; /* Virtual Clock kept in CPU cycles */
* ((__FreeBSD__ + 0) < 5). No, we can't remove "+ 0" from
* ((__FreeBSD__ + 0) < 5).
*/
- #if defined(VM_X86_64)
+ #if defined(VM_X86_64) || defined(VM_ARM_64)
#define FMTSZ "l"
#define FMTPD "l"
#else
@@ -339,7 +414,7 @@ typedef int64 VmTimeVirtualClock; /* Virtual Clock kept in CPU cycles */
/* BSD, Linux */
#define FMTSZ "z"
- #if defined(VM_X86_64)
+ #if defined(VM_X86_64) || defined(VM_ARM_64)
#define FMTPD "l"
#else
#define FMTPD ""
@@ -347,13 +422,13 @@ typedef int64 VmTimeVirtualClock; /* Virtual Clock kept in CPU cycles */
#else
/* Systems with a pre-C99 libc */
#define FMTSZ "Z"
- #if defined(VM_X86_64)
+ #if defined(VM_X86_64) || defined(VM_ARM_64)
#define FMTPD "l"
#else
#define FMTPD ""
#endif
#endif
- #if defined(VM_X86_64)
+ #if defined(VM_X86_64) || defined(VM_ARM_64)
#define FMT64 "l"
#elif defined(sun) || defined(__FreeBSD__)
#define FMT64 "ll"
@@ -384,7 +459,7 @@ typedef int64 VmTimeVirtualClock; /* Virtual Clock kept in CPU cycles */
#define CONST64(c) c##LL
#define CONST64U(c) c##uLL
#elif __GNUC__
-#if defined(VM_X86_64)
+#if defined(VM_X86_64) || defined(VM_ARM_64)
#define CONST64(c) c##L
#define CONST64U(c) c##uL
#else
@@ -404,7 +479,7 @@ typedef int64 VmTimeVirtualClock; /* Virtual Clock kept in CPU cycles */
* more than 31 on a 64-bit compile.
*/
-#if defined(VM_X86_64)
+#if defined(VM_X86_64) || defined(VM_ARM_64)
#define CONST3264(a) CONST64(a)
#define CONST3264U(a) CONST64U(a)
#else
@@ -442,7 +517,7 @@ typedef uint8 *TCA; /* Pointer into TC (usually). */
* Type big enough to hold an integer between 0..100
*/
typedef uint8 Percent;
-#define AsPercent(v) ((Percent)(v))
+#define AsPercent(v) ((Percent)(v))
typedef uintptr_t VA;
@@ -461,7 +536,16 @@ typedef uint64 PhysMemSize;
#ifndef __STRICT_ANSI__
typedef uint64 BA;
#endif
-typedef uint32 BPN;
+
+#ifdef VMKERNEL
+typedef void *BPN;
+#else
+typedef uint64 BPN;
+#endif
+
+#define UINT64_2_BPN(u) ((BPN)(u))
+#define BPN_2_UINT64(b) ((uint64)(b))
+
typedef uint32 PageNum;
typedef unsigned MemHandle;
typedef unsigned int IoHandle;
@@ -488,10 +572,25 @@ typedef User_CartelID User_CartelGroupID;
typedef uint32 Worldlet_ID;
#define INVALID_WORLDLET_ID ((Worldlet_ID)-1)
+typedef int8 Reg8;
+typedef int16 Reg16;
+typedef int32 Reg32;
+typedef int64 Reg64;
+
+typedef uint8 UReg8;
+typedef uint16 UReg16;
+typedef uint32 UReg32;
+typedef uint64 UReg64;
+
+#if defined(VMM) || defined(COREQUERY) || defined(EXTDECODER) || \
+ defined (VMKERNEL) || defined (VMKBOOT)
+typedef Reg64 Reg;
+typedef UReg64 UReg;
+#endif
/* The Xserver source compiles with -ansi -pendantic */
#ifndef __STRICT_ANSI__
typedef uint64 MA;
-typedef uint32 MPN;
+typedef uint32 MPN32;
#endif
/*
@@ -544,7 +643,7 @@ typedef uint64 LPN64;
typedef uint64 PA64;
typedef uint64 PPN64;
typedef uint64 MA64;
-typedef uint64 MPN64;
+typedef uint64 MPN;
/*
* IO device DMA virtual address and page number (translated by IOMMU to
@@ -568,22 +667,22 @@ typedef void * UserVA;
#endif
-#define MAX_PPN_BITS 30
+#define MAX_PPN_BITS 31
#define MAX_PPN (((PPN)1 << MAX_PPN_BITS) - 1) /* Maximal observable PPN value. */
#define INVALID_PPN ((PPN)0xffffffff)
#define APIC_INVALID_PPN ((PPN)0xfffffffe)
-#define INVALID_BPN ((BPN)0x3fffffff)
+#define INVALID_BPN ((BPN)0x000000ffffffffffull)
-#define MPN38_MASK ((1ull << 38) - 1) /* imposed by vmkernel pframes */
+#define MPN38_MASK ((1ull << 38) - 1)
-#define RESERVED_MPN ((MPN64)0)
-#define INVALID_MPN ((MPN64)MPN38_MASK)
-#define MEMREF_MPN ((MPN64)MPN38_MASK - 1)
-#define RELEASED_MPN ((MPN64)MPN38_MASK - 2)
+#define RESERVED_MPN ((MPN)0)
+#define INVALID_MPN ((MPN)MPN38_MASK)
+#define MEMREF_MPN ((MPN)MPN38_MASK - 1)
+#define RELEASED_MPN ((MPN)MPN38_MASK - 2)
/* account for special MPNs defined above */
-#define MAX_MPN ((MPN64)MPN38_MASK - 3) /* 50 bits of address space */
+#define MAX_MPN ((MPN)MPN38_MASK - 3) /* 50 bits of address space */
#define INVALID_IOPN ((IOPN)-1)
#define MAX_IOPN (INVALID_IOPN - 1)
@@ -595,10 +694,10 @@ typedef void * UserVA;
/*
* Format modifier for printing VA, LA, and VPN.
- * Use them like this: Log("%#"FMTLA"x\n", laddr)
+ * Use them like this: Log("%#" FMTLA "x\n", laddr)
*/
-#if defined(VMM) || defined(FROBOS64) || vm_x86_64 || defined __APPLE__
+#if defined(VMM) || defined(FROBOS64) || vm_x86_64 || vm_arm_64 || defined __APPLE__
# define FMTLA "l"
# define FMTVA "l"
# define FMTVPN "l"
@@ -711,6 +810,8 @@ typedef void * UserVA;
#if defined(__GNUC__)
#define ABSOLUTELY_NOINLINE __attribute__((__noinline__))
+#elif defined(_MSC_VER)
+#define ABSOLUTELY_NOINLINE __declspec(noinline)
#endif
/*
@@ -903,6 +1004,9 @@ typedef void * UserVA;
# else
typedef uint32 size_t;
# endif
+# elif defined(VM_ARM_64)
+# define _SIZE_T
+ typedef uint64 size_t;
# elif defined(__arm__)
# define _SIZE_T
typedef uint32 size_t;
@@ -923,6 +1027,12 @@ typedef void * UserVA;
# else
typedef int32 ssize_t;
# endif
+# elif defined(VM_ARM_64)
+# define _SSIZE_T
+# define __ssize_t_defined
+# define _SSIZE_T_DECLARED
+# define _SSIZE_T_DEFINED_
+ typedef int64 ssize_t;
# elif defined(__arm__)
# define _SSIZE_T
# define __ssize_t_defined
@@ -937,7 +1047,7 @@ typedef void * UserVA;
/*
* Format modifier for printing pid_t. On sun the pid_t is a ulong, but on
* Linux it's an int.
- * Use this like this: printf("The pid is %"FMTPID".\n", pid);
+ * Use this like this: printf("The pid is %" FMTPID ".\n", pid);
*/
#ifdef sun
# ifdef VM_X86_64
@@ -952,7 +1062,7 @@ typedef void * UserVA;
/*
* Format modifier for printing uid_t. On Solaris 10 and earlier, uid_t
* is a ulong, but on other platforms it's an unsigned int.
- * Use this like this: printf("The uid is %"FMTUID".\n", uid);
+ * Use this like this: printf("The uid is %" FMTUID ".\n", uid);
*/
#if defined(sun) && !defined(SOL11)
# ifdef VM_X86_64
@@ -967,7 +1077,7 @@ typedef void * UserVA;
/*
* Format modifier for printing mode_t. On sun the mode_t is a ulong, but on
* Linux it's an int.
- * Use this like this: printf("The mode is %"FMTMODE".\n", mode);
+ * Use this like this: printf("The mode is %" FMTMODE ".\n", mode);
*/
#ifdef sun
# ifdef VM_X86_64
@@ -984,7 +1094,7 @@ typedef void * UserVA;
* a long int, but on FreeBSD (as of 5.0, it seems), the time_t is a signed
* size quantity. Refer to the definition of FMTSZ to see why we need silly
* preprocessor arithmetic.
- * Use this like this: printf("The mode is %"FMTTIME".\n", time);
+ * Use this like this: printf("The mode is %" FMTTIME ".\n", time);
*/
#if defined(__FreeBSD__) && (__FreeBSD__ + 0) && ((__FreeBSD__ + 0) >= 5)
# define FMTTIME FMTSZ"d"
diff --git a/open-vm-tools/lib/include/vm_device_version.h b/open-vm-tools/lib/include/vm_device_version.h
index 81b89a90..d9d0dacd 100644
--- a/open-vm-tools/lib/include/vm_device_version.h
+++ b/open-vm-tools/lib/include/vm_device_version.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
+ * Copyright (C) 1998,2005-2012,2014-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -71,7 +71,6 @@
#define PCI_DEVICE_ID_VMWARE_BRIDGE 0x0790
#define PCI_DEVICE_ID_VMWARE_ROOTPORT 0x07A0
#define PCI_DEVICE_ID_VMWARE_VMXNET3 0x07B0
-#define PCI_DEVICE_ID_VMWARE_VMXWIFI 0x07B8
#define PCI_DEVICE_ID_VMWARE_PVSCSI 0x07C0
#define PCI_DEVICE_ID_VMWARE_82574 0x07D0
#define PCI_DEVICE_ID_VMWARE_AHCI 0x07E0
@@ -91,6 +90,9 @@
#define PCI_DEVICE_ID_VMWARE_DUMMY 0x0809
+#define PCI_DEVICE_ID_VMWARE_NVDIMM 0x0810
+#define PCI_DEVICE_ID_VMWARE_VRDMA 0x0820
+
/*
* VMware Virtual Device Test Infrastructure (VDTI) devices
*/
@@ -256,6 +258,12 @@
/************* USB implementation limits ********************************/
#define MAX_USB_DEVICES_PER_HOST_CONTROLLER 127
+/************* NVDIMM implementation limits ********************************/
+#define MAX_NVDIMM 64
+
+/************* vRDMA implementation limits ******************************/
+#define MAX_VRDMA_DEVICES 2
+
/************* Strings for Host USB Driver *******************************/
#ifdef _WIN32
diff --git a/open-vm-tools/lib/include/vm_legal.h b/open-vm-tools/lib/include/vm_legal.h
index fcd706f7..56affb5f 100644
--- a/open-vm-tools/lib/include/vm_legal.h
+++ b/open-vm-tools/lib/include/vm_legal.h
@@ -32,6 +32,10 @@
#endif
+/*
+ * The following strings may be incorporated into MSGID strings. Updating
+ * them therefore may require updating translations and vmsg auditing files.
+ */
#define COPYRIGHT_YEARS "1998-2015"
#define COPYRIGHT_STRING "Copyright (C) " COPYRIGHT_YEARS " " COMPANY_NAME
#define RIGHT_RESERVED "All rights reserved."
diff --git a/open-vm-tools/lib/include/vm_product.h b/open-vm-tools/lib/include/vm_product.h
index 362fedce..a1822758 100644
--- a/open-vm-tools/lib/include/vm_product.h
+++ b/open-vm-tools/lib/include/vm_product.h
@@ -68,6 +68,8 @@
#define PRODUCT_ACE_PLAYER_BRIEF_NAME "ACE " PRODUCT_PLAYER_BRIEF_NAME
#define PRODUCT_MAC_DESKTOP_BRIEF_NAME "Fusion"
#define PRODUCT_ACE_MANAGEMENT_SERVER_BRIEF_NAME "ACE Management Server"
+#define PRODUCT_VMRC_BRIEF_NAME "Remote Console"
+#define PRODUCT_GANTRY_BRIEF_NAME "Gantry"
/*
@@ -92,6 +94,10 @@
#define PRODUCT_ACE_PLAYER_NAME MAKE_NAME(PRODUCT_ACE_PLAYER_BRIEF_NAME)
#define PRODUCT_ACE_MANAGEMENT_SERVER_NAME MAKE_NAME(PRODUCT_ACE_MANAGEMENT_SERVER_BRIEF_NAME)
#define PRODUCT_MAC_DESKTOP_NAME_FOR_LICENSE "VMware Fusion for Mac OS"
+#define PRODUCT_VMRC_NAME MAKE_NAME(PRODUCT_VMRC_BRIEF_NAME)
+#define PRODUCT_VMRC_NAME_FOR_LICENSE PRODUCT_VMRC_NAME
+#define PRODUCT_GANTRY_NAME MAKE_NAME(PRODUCT_GANTRY_BRIEF_NAME)
+#define PRODUCT_GANTRY_NAME_FOR_LICENSE PRODUCT_GANTRY_NAME
#define PRODUCT_VMLS_SHORT_NAME "VMLS"
#define PRODUCT_VMLS_NAME MAKE_NAME("License Server")
@@ -138,7 +144,7 @@
#define PRODUCT_VDDK_SHORT_NAME "VDDK"
#define PRODUCT_VDDK_NAME MAKE_NAME("Virtual Disk Development Kit")
-#define PRODUCT_VDM_CLIENT_NAME MAKE_NAME("Horizon View Client")
+#define PRODUCT_VDM_CLIENT_NAME MAKE_NAME("Horizon Client")
#define PRODUCT_VDM_CLIENT_NAME_FOR_LICENSE PRODUCT_VDM_CLIENT_NAME
#define PRODUCT_XVP_SHORT_NAME "XVP"
@@ -149,10 +155,16 @@
#define PRODUCT_HBR_SERVER_NAME MAKE_NAME("vSphere Replication Server")
-#define PRODUCT_VIEW_SHORT_NAME "View"
-#define PRODUCT_VIEW_NAME MAKE_NAME("View")
+#define PRODUCT_VIEW_SHORT_NAME "Horizon View"
+#define PRODUCT_VIEW_NAME MAKE_NAME("Horizon View")
#define PRODUCT_VIEW_NAME_FOR_LICENSE PRODUCT_VIEW_NAME
+#define PRODUCT_FLEX_GENERIC_SHORT_NAME "Horizon FLEX"
+#define PRODUCT_FLEX_GENERIC_NAME MAKE_NAME(PRODUCT_FLEX_GENERIC_SHORT_NAME)
+
+#define PRODUCT_FLEX_SERVER_SHORT_NAME PRODUCT_FLEX_GENERIC_SHORT_NAME " Server"
+#define PRODUCT_FLEX_SERVER_NAME MAKE_NAME(PRODUCT_FLEX_SERVER_SHORT_NAME)
+
#define PRODUCT_VMCF_NAME MAKE_NAME("VMCF")
// XXX VMvisor is the underlying technology for possibly several products,
@@ -168,54 +180,6 @@
#endif
/*
- * VMware Remote Console (VMRC) version definitions
- */
-
-#define PRODUCT_VMRC_SHORT_NAME "VMRC"
-#define PRODUCT_VMRC_NAME MAKE_NAME("Remote Console")
-#define PRODUCT_VMRC_PLUGIN_NAME PRODUCT_VMRC_NAME " Plug-in"
-#define PRODUCT_VMRC_DESCRIPTION "Enables remote interaction with virtual machines."
-#ifdef _WIN32
-#define PRODUCT_VMRC_EXECUTABLE PRODUCT_GENERIC_NAME_LOWER "-vmrc.exe"
-#else
-#define PRODUCT_VMRC_EXECUTABLE PRODUCT_GENERIC_NAME_LOWER "-vmrc"
-#define PRODUCT_VMRC_DEVICE_EXECUTABLE PRODUCT_GENERIC_NAME_LOWER "-deviceMgr"
-#endif
-
-/*
- * VMRC ActiveX CLSIDs and ProgIDs
- *
- * VMRC is versioned x.y.z - ProgID is intentionally built using only x.y
- */
-#define PRODUCT_VMRC_PLUGIN_GUID_EMBEDDED 4AEA1010-0A0C-405E-9B74-767FC8A998CB
-#define PRODUCT_VMRC_PLUGIN_GUID_TYPELIB E82F3B76-A628-4486-B197-03780F86063A
-#define PRODUCT_VMRC_PLUGIN_PROGID_EMBEDDED_BASE "VMware.RemoteConsole"
-#define PRODUCT_VMRC_PLUGIN_PROGID_EMBEDDED PRODUCT_VMRC_PLUGIN_PROGID_EMBEDDED_BASE "." \
- XSTR(VMRC_PLUGIN_VERSION_BASE)
-
-/*
- * VMRC MIME types
- */
-#ifdef _WIN32
-#define PRODUCT_VMRC_MIMETYPE_SEPARATOR "|"
-#define PRODUCT_VMRC_MIMETYPE_TERMINATOR ""
-#else
-#define PRODUCT_VMRC_MIMETYPE_SEPARATOR "::" PRODUCT_VMRC_PLUGIN_NAME ";"
-#define PRODUCT_VMRC_MIMETYPE_TERMINATOR "::" PRODUCT_VMRC_PLUGIN_NAME ";"
-#endif
-
-#define PRODUCT_VMRC_PLUGIN_CURRENT_MIMETYPE \
- "application/x-vmware-remote-console-2012"
-
-/*
- * All supported plugin mimetypes
- *
- * NB: See above for constraints on the ordering of this list.
- */
-#define PRODUCT_VMRC_PLUGIN_MIMETYPES \
- PRODUCT_VMRC_PLUGIN_CURRENT_MIMETYPE PRODUCT_VMRC_MIMETYPE_TERMINATOR
-
-/*
* VMware USB Arbitration Service version definitions
*/
@@ -227,6 +191,10 @@
#define PRODUCT_USB_ARBITRATOR_EXECUTABLE PRODUCT_GENERIC_NAME_LOWER "-usbarbitrator"
#endif
+// VMware Remote Console (VMRC)
+#define PRODUCT_VMRC_UPPER "VMRC"
+#define PRODUCT_VMRC_LOWER "vmrc"
+
/*
* TODO: This properly lives in productState, but we need it here to
* define DEFAULT_LIBDIRECTORY. If that can be moved to productState,
@@ -238,7 +206,7 @@
#if !( defined(VMX86_SERVER) \
|| defined(VMX86_DESKTOP) \
|| defined(VMX86_ENTERPRISE_DESKTOP) \
- || defined(VMX86_VIEW) \
+ || defined(VMX86_HORIZON_VIEW) \
|| defined(VMX86_MUI) \
|| defined(VMX86_VPX) \
|| defined(VMX86_WBC) \
@@ -255,7 +223,9 @@
|| defined(VMX86_NETDUMP) \
|| defined(VMX86_BOOMERANG) \
|| defined(VMX86_HBR_SERVER) \
- || defined(VMX86_VMCF))
+ || defined(VMX86_VMCF) \
+ || defined(VMX86_GANTRY) \
+ || defined(VMX86_VMRC))
# if defined(_WIN32) || defined(__APPLE__)
/*
* XXX Make the product be Workstation by default if none of the defines
@@ -276,6 +246,10 @@
# define PRODUCT_SHORT_NAME PRODUCT_CONSOLE_NAME
#elif defined(VMX86_MUI)
# define PRODUCT_SHORT_NAME PRODUCT_MUI_NAME
+#elif defined(VMX86_VMRC) /* check VMX86_VMRC before VMX86_DESKTOP */
+# define PRODUCT_SHORT_NAME PRODUCT_VMRC_NAME
+#elif defined(VMX86_GANTRY)
+# define PRODUCT_SHORT_NAME PRODUCT_GANTRY_NAME
#elif defined(VMX86_ENTERPRISE_DESKTOP)
# define PRODUCT_SHORT_NAME PRODUCT_WORKSTATION_ENTERPRISE_NAME
#elif defined(VMX86_DESKTOP)
@@ -288,7 +262,7 @@
# define PRODUCT_SHORT_NAME VMWARE_TOOLS_SHORT_NAME
#elif defined(VMX86_VPX)
# if defined(CSI_HA)
-# define PRODUCT_SHORT_NAME PRODUCT_HA_NAME
+# define PRODUCT_SHORT_NAME PRODUCT_HA_NAME
# elif defined(CSI_FDM)
# define PRODUCT_SHORT_NAME PRODUCT_FDM_NAME
# elif defined(VPXA)
@@ -330,7 +304,7 @@
# define PRODUCT_SHORT_NAME PRODUCT_BOOMERANG_NAME
#elif defined(VMX86_HBR_SERVER)
# define PRODUCT_SHORT_NAME PRODUCT_HBR_SERVER_NAME
-#elif defined(VMX86_VIEW)
+#elif defined(VMX86_HORIZON_VIEW)
# define PRODUCT_SHORT_NAME PRODUCT_VIEW_NAME
#elif defined(VMX86_VMCF)
# define PRODUCT_SHORT_NAME PRODUCT_VMCF_NAME
@@ -393,6 +367,12 @@
# if defined(VMX86_SERVER)
# define PRODUCT_NAME_FOR_LICENSE "VMware ESX Server"
# define PRODUCT_SMP_NAME_FOR_LICENSE PRODUCT_ESX_SMP_NAME
+# elif defined(VMX86_VMRC) /* check VMX86_VMRC before VMX86_DESKTOP */
+# define PRODUCT_NAME_FOR_LICENSE PRODUCT_VMRC_NAME_FOR_LICENSE
+# define PRODUCT_SMP_NAME_FOR_LICENSE "" // None
+# elif defined(VMX86_GANTRY)
+# define PRODUCT_NAME_FOR_LICENSE PRODUCT_GANTRY_NAME_FOR_LICENSE
+# define PRODUCT_SMP_NAME_FOR_LICENSE "" // None
# elif defined(VMX86_DESKTOP)
# if defined(__APPLE__)
# define PRODUCT_NAME_FOR_LICENSE PRODUCT_MAC_DESKTOP_NAME_FOR_LICENSE
@@ -483,7 +463,10 @@
* a license intended for one flavor of the product will not allow
* another flavor of the product to run.
*/
-# if defined(VMX86_DESKTOP)
+# if defined(VMX86_VMRC) /* check VMX86_VMRC before VMX86_DESKTOP */
+# define PRODUCT_NAME_FOR_LICENSE PRODUCT_VMRC_NAME
+# define PRODUCT_SMP_NAME_FOR_LICENSE "" // None
+# elif defined(VMX86_DESKTOP)
# if defined(__APPLE__)
# define PRODUCT_NAME_FOR_LICENSE PRODUCT_MAC_DESKTOP_NAME_FOR_LICENSE
# else
@@ -568,10 +551,4 @@
// VMRC uses it.
#define VMWARE_HTTPSPROXY "VMWARE_HTTPSPROXY"
-// Name of the environment variable that controls whether MKS traffic should
-// be tunnelled over HTTPS through the console proxy. Currently vCloud VMRC
-// uses it.
-#define VMWARE_HTTPSTUNNEL_MKS "VMWARE_HTTPSTUNNEL_MKS"
-
-
#endif /* VM_PRODUCT_H */
diff --git a/open-vm-tools/lib/include/vm_product_versions.h b/open-vm-tools/lib/include/vm_product_versions.h
index 275fd523..9793bbe8 100644
--- a/open-vm-tools/lib/include/vm_product_versions.h
+++ b/open-vm-tools/lib/include/vm_product_versions.h
@@ -32,9 +32,16 @@
* When building the Tools, we make an effort to follow the "internal" Tools
* version. Otherwise we use a hard-coded value for Workstation and a different
* hard-coded value for every other product.
+ *
+ * Note: VMX86_VIEWCLIENT must be before VMX86_DESKTOP so that crtbora
+ * versioning is correct.
*/
-#if defined(VMX86_DESKTOP)
- #define PRODUCT_VERSION 10,0,0,PRODUCT_BUILD_NUMBER_NUMERIC /* WORKSTATION_VERSION_NUMBER below has to match this */
+#if defined(VMX86_VIEWCLIENT)
+ #define PRODUCT_VERSION 3,0,0,PRODUCT_BUILD_NUMBER_NUMERIC
+#elif defined(VMX86_VMRC) /* check VMX86_VMRC before VMX86_DESKTOP */
+ #define PRODUCT_VERSION 7,0,1,PRODUCT_BUILD_NUMBER_NUMERIC /* VMRC_VERSION_NUMBER below has to match this */
+#elif defined(VMX86_DESKTOP)
+ #define PRODUCT_VERSION 12,0,0,PRODUCT_BUILD_NUMBER_NUMERIC /* WORKSTATION_VERSION_NUMBER below has to match this */
#elif defined(VMX86_TOOLS)
#define PRODUCT_VERSION TOOLS_VERSION_EXT_CURRENT_CSV
#elif defined(VMX86_VCB)
@@ -46,10 +53,10 @@
#define PRODUCT_VERSION 6,0,0,PRODUCT_BUILD_NUMBER_NUMERIC
#elif defined(VMX86_BOOMERANG)
#define PRODUCT_VERSION 1,0,0,PRODUCT_BUILD_NUMBER_NUMERIC
-#elif defined(VMX86_VIEW)
+#elif defined(VMX86_HORIZON_VIEW)
#define PRODUCT_VERSION 0,0,0,PRODUCT_BUILD_NUMBER_NUMERIC
#else
- #define PRODUCT_VERSION 6,0,0,PRODUCT_BUILD_NUMBER_NUMERIC /* PLAYER_VERSION_NUMBER below has to match this */
+ #define PRODUCT_VERSION 8,0,0,PRODUCT_BUILD_NUMBER_NUMERIC /* PLAYER_VERSION_NUMBER below has to match this */
#endif
/*
@@ -133,7 +140,7 @@
#define ESX_VERSION_THIRD_PARTY ESX_VERSION_MAJOR ESX_VERSION_MINOR \
ESX_VERSION_MAINT
#define ESX_RELEASE_UPDATE "0" /* 0 = Pre-release/GA, 1 = Update 1 */
-#define ESX_RELEASE_PATCH "11" /* 0 = experimental */
+#define ESX_RELEASE_PATCH "0" /* 0 = experimental */
#define ESX_RELEASE ESX_RELEASE_UPDATE "." ESX_RELEASE_PATCH
#define VMSERVER_VERSION "e.x.p"
#define WORKSTATION_RELEASE_DESCRIPTION ""
@@ -150,12 +157,19 @@
* HEADS UP: Don't merge patch version bumps (e.g. x.y.0 -> x.y.1) to CBS
* branches (*-main), 'cuz it breaks stuff in VIX land. See bug 939456.
*
+ * Whenever WORKSTATION_VERSION_NUMBER and PLAYER_VERSION_NUMBER are changed,
+ * necessary VIX changes also need to be done. See bug 939456.
+ *
* ALSO, leave FOO_VERSION at e.x.p on all EXCEPT release branches.
*/
-#define WORKSTATION_VERSION_NUMBER "10.0.0" /* this version number should always match real WS version number */
+#define WORKSTATION_VERSION_NUMBER "12.0.0" /* this version number should always match real WS version number */
#define WORKSTATION_VERSION "e.x.p"
-#define PLAYER_VERSION_NUMBER "6.0.0" /* this version number should always match real Player version number */
+#define PLAYER_VERSION_NUMBER "8.0.0" /* this version number should always match real Player version number */
#define PLAYER_VERSION "e.x.p"
+#define VMRC_VERSION_NUMBER "7.0.1" /* this version number should always match real VMRC version number */
+#define VMRC_VERSION "7.0.1"
+
+#define GANTRY_VERSION "e.x.p"
/*
* In the *-main branches, FUSION_VERSION should always be set to "e.x.p".
@@ -191,16 +205,14 @@
#define SSO_VERSION "1.0.0"
#define WBC_VERSION "5.1.0"
#define SDK_VERSION "4.1.0"
-#define FOUNDRY_VERSION "1.13.0"
-#define FOUNDRY_FILE_VERSION 1,13,0,PRODUCT_BUILD_NUMBER_NUMERIC
+#define FOUNDRY_VERSION "1.15.0"
+#define FOUNDRY_FILE_VERSION 1,15,0,PRODUCT_BUILD_NUMBER_NUMERIC
#define VMLS_VERSION "e.x.p"
#define VLICENSE_VERSION "1.1.5"
#define DDK_VERSION "e.x.p"
#define VIPERL_VERSION "1.1.0"
#define RCLI_VERSION "6.0.0"
#define VDM_VERSION "e.x.p"
-#define VMSAFE_VERSION "1.2.0"
-#define VMSAFE_FILE_VERSION 1,2,0,PRODUCT_BUILD_NUMBER_NUMERIC
#define NETDUMP_VERSION "5.1.0"
#define NETDUMP_FILE_VERSION 5,1,0,PRODUCT_BUILD_NUMBER_NUMERIC
#define VDDK_VERSION "6.0.0"
@@ -208,12 +220,13 @@
#define OVFTOOL_VERSION "4.1.0"
#define VCSA_INSTALLER_VERSION "1.0.0"
#define OVFTOOL_FILE_VERSION 4,1,0,PRODUCT_BUILD_NUMBER_NUMERIC
-#define VDM_CLIENT_VERSION "e.x.p"
+#define VDM_CLIENT_VERSION "3.0.0"
#define VGAUTH_VERSION "e.x.p"
+#define COMMON_AGENT_VERSION "e.x.p"
#define VIEWY_VERSION "e.x.p"
#define VMCFSDK_VERSION "e.x.p"
#define PCOIP_VERSION "e.x.p"
-#define VIEW_VERSION "0.0.0"
+#define VIEW_VERSION "6.1.1"
#define HOSTD_VERSION "e.x.p"
#define RECOVERYLIBS_VERSION "2.0.0"
#define PRECHECK_VERSION "e.x.p"
@@ -222,6 +235,12 @@
#define VIEW_CLIENT_VERSION "e.x.p"
#define VHSESDK_VERSION "1.0.0"
#define RDE_RFT_ALL_VERSION "2.3.0"
+#define RDESDK_VERSION "2.0.0"
+#define RDESDKREL_VERSION "2.0.0"
+#define MKSVCHANDEV_VERSION "1.0.0"
+#define FRDEV_VERSION "1.0.0"
+#define TSMMRDEV_VERSION "1.0.0"
+#define VIEWMPDEV_VERSION "1.0.0"
#ifndef MAKESTR
@@ -229,30 +248,6 @@
#define XSTR(x) MAKESTR(x)
#endif
-// This extra version define is here so the Makefiles can easily pick it up.
-// See the VMRC_PLUGIN_VERSION section in /mk/defs-onetime.mk
-
-#define VMRC_PLUGIN_VERSION_MAJOR 5
-#define VMRC_PLUGIN_VERSION_MINOR 5
-#define VMRC_PLUGIN_VERSION_Z 0
-
-/*
- * TODO: figure out why the following breaks linux installer
- * #define VMRC_PLUGIN_VERSION_NUMBER \
- * XSTR(VMRC_PLUGIN_VERSION_MAJOR) "." XSTR(VMRC_PLUGIN_VERSION_MINOR) "." XSTR(VMRC_PLUGIN_VERSION_Z)
- */
-#define VMRC_PLUGIN_VERSION_NUMBER "5.5.0"
-
-/* this version number should always match real VMRC & plugin version number */
-#define VMRC_VERSION VMRC_PLUGIN_VERSION_NUMBER
-
-#define VMRC_PLUGIN_VERSION_BASE VMRC_PLUGIN_VERSION_MAJOR.VMRC_PLUGIN_VERSION_MINOR
-
-#define VMRC_PLUGIN_VERSION \
- XSTR(VMRC_PLUGIN_VERSION_BASE) "." XSTR(VMRC_PLUGIN_VERSION_Z) "." BUILD_NUMBER_NUMERIC_STRING
-#define VMRC_PLUGIN_VERSION_COMMAS \
- VMRC_PLUGIN_VERSION_MAJOR,VMRC_PLUGIN_VERSION_MINOR,0,PRODUCT_BUILD_NUMBER_NUMERIC
-
/*
* The current Tools version, derived from vm_tools_version.h. Do not modify this.
*/
@@ -268,7 +263,13 @@
#define VIM_ESX_PRODUCT_LINE_ID "esx"
#define VIM_WS_PRODUCT_LINE_ID "ws"
-#if defined(VMX86_SERVER)
+#if defined(VMX86_VIEWCLIENT)
+# define PRODUCT_VERSION_NUMBER VDM_CLIENT_VERSION
+#elif defined(VMX86_VMRC) /* check VMX86_VMRC before VMX86_DESKTOP */
+# define PRODUCT_VERSION_NUMBER VMRC_VERSION
+#elif defined(VMX86_GANTRY)
+# define PRODUCT_VERSION_NUMBER GANTRY_VERSION
+#elif defined(VMX86_SERVER)
# define PRODUCT_VERSION_NUMBER ESX_VERSION
#elif defined(VMX86_MUI)
# define PRODUCT_VERSION_NUMBER MUI_VERSION
@@ -314,7 +315,7 @@
# define PRODUCT_VERSION_NUMBER BOOMERANG_VERSION
#elif defined(VMX86_HBR_SERVER)
# define PRODUCT_VERSION_NUMBER ESX_VERSION
-#elif defined(VMX86_VIEW)
+#elif defined(VMX86_HORIZON_VIEW)
# define PRODUCT_VERSION_NUMBER VIEW_VERSION
#endif
@@ -340,7 +341,9 @@
* a parameter that no longer match the content of the dormant license
* file.
*/
-#define PRODUCT_MAC_DESKTOP_VERSION_STRING_FOR_LICENSE "6.0"
+#define PRODUCT_MAC_DESKTOP_VERSION_STRING_FOR_LICENSE "7.0"
+#define PRODUCT_PLAYER_VERSION_STRING_FOR_LICENSE "7.0"
+#define PRODUCT_VMRC_VERSION_STRING_FOR_LICENSE "7.0"
#if defined(VMX86_TOOLS)
/* This product doesn't use a license */
@@ -349,6 +352,10 @@
#else
# if defined(VMX86_SERVER)
# define PRODUCT_LICENSE_VERSION "6.0"
+# elif defined(VMX86_VMRC) /* check VMX86_VMRC before VMX86_DESKTOP */
+# define PRODUCT_LICENSE_VERSION PRODUCT_VMRC_VERSION_STRING_FOR_LICENSE
+# elif defined(VMX86_GANTRY)
+# define PRODUCT_LICENSE_VERSION "1.0"
# elif defined(VMX86_WGS_MIGRATION)
# define PRODUCT_LICENSE_VERSION "1.0"
# elif defined(VMX86_WGS)
@@ -359,7 +366,7 @@
# if defined(__APPLE__)
# define PRODUCT_LICENSE_VERSION PRODUCT_MAC_DESKTOP_VERSION_STRING_FOR_LICENSE
# else
-# define PRODUCT_LICENSE_VERSION "10.0"
+# define PRODUCT_LICENSE_VERSION "11.0"
# endif
# elif defined(VMX86_VPX)
# define PRODUCT_LICENSE_VERSION "6.0"
@@ -376,8 +383,6 @@
# define PRODUCT_VERSION_STRING_FOR_LICENSE PRODUCT_LICENSE_VERSION
#endif
-#define PRODUCT_PLAYER_VERSION_STRING_FOR_LICENSE "6.0"
-
/*
* This is for ACE Management Server
* Since there is no separate product defined for Ace Mgmt Server
@@ -452,6 +457,8 @@
#define PRODUCT_VERSION_WORKSTATION_80 PRODUCT_WORKSTATION_BRIEF_NAME " 8.0"
#define PRODUCT_VERSION_WORKSTATION_90 PRODUCT_WORKSTATION_BRIEF_NAME " 9.0"
#define PRODUCT_VERSION_WORKSTATION_100 PRODUCT_WORKSTATION_BRIEF_NAME " 10.0"
+#define PRODUCT_VERSION_WORKSTATION_110 PRODUCT_WORKSTATION_BRIEF_NAME " 11.0"
+#define PRODUCT_VERSION_WORKSTATION_120 PRODUCT_WORKSTATION_BRIEF_NAME " 12.0"
#define PRODUCT_VERSION_WORKSTATION_ENTERPRISE_1 "ACE 1.x"
#define PRODUCT_VERSION_WORKSTATION_ENTERPRISE_2 "ACE 2.0"
#define PRODUCT_VERSION_WORKSTATION_ENTERPRISE_25 "ACE 2.5"
@@ -462,4 +469,7 @@
#define PRODUCT_VERSION_MAC_DESKTOP_40 PRODUCT_MAC_DESKTOP_BRIEF_NAME " 4.0"
#define PRODUCT_VERSION_MAC_DESKTOP_50 PRODUCT_MAC_DESKTOP_BRIEF_NAME " 5.0"
#define PRODUCT_VERSION_MAC_DESKTOP_60 PRODUCT_MAC_DESKTOP_BRIEF_NAME " 6.0"
+#define PRODUCT_VERSION_MAC_DESKTOP_70 PRODUCT_MAC_DESKTOP_BRIEF_NAME " 7.0"
+#define PRODUCT_VERSION_MAC_DESKTOP_80 PRODUCT_MAC_DESKTOP_BRIEF_NAME " 8.0"
+#define PRODUCT_VERSION_VMRC_70 PRODUCT_VMRC_BRIEF_NAME " 7.0"
#endif
diff --git a/open-vm-tools/lib/include/vm_tools_version.h b/open-vm-tools/lib/include/vm_tools_version.h
index b486a0b2..b952c5b2 100644
--- a/open-vm-tools/lib/include/vm_tools_version.h
+++ b/open-vm-tools/lib/include/vm_tools_version.h
@@ -63,6 +63,16 @@
#ifndef RC_INVOKED
typedef uint32 ToolsVersion;
+typedef enum {
+ TOOLS_TYPE_UNSET = -1,
+ TOOLS_TYPE_UNKNOWN = 0,
+ TOOLS_TYPE_MSI,
+ TOOLS_TYPE_TARBALL,
+ TOOLS_TYPE_OSP,
+ TOOLS_TYPE_OVT,
+ TOOLS_TYPE_MAX,
+} ToolsInstallType;
+
typedef struct {
uint8 major;
uint8 minor;
@@ -91,6 +101,9 @@ TOOLS_VERSION_UINT_TO_COMPONENTS(const ToolsVersion toolsVersion, // IN
*/
#define TOOLS_VERSION_UNMANAGED 0x7fffffff
+/* Historically -1 indicates tools version is not available. */
+#define TOOLS_VERSION_INVALID 0xffffffff
+
#define STRINGER(MJR, MNR, BASE) #MJR "." #MNR "." #BASE
#define TOOLS_VERSION_STRINGER(MJR, MNR, BASE) STRINGER(MJR, MNR, BASE)
@@ -1239,19 +1252,61 @@ TOOLS_VERSION_UINT_TO_COMPONENTS(const ToolsVersion toolsVersion, // IN
#define TOOLS_VERSION_2015_RC_V_BASE 3
#ifndef RC_INVOKED
+#define TOOLS_VERSION_HOSTED14_TECHPREVIEW1 TOOLS_VERSION_TO_UINT(TOOLS_VERSION_HOSTED14_TECHPREVIEW1_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_HOSTED14_TECHPREVIEW1_V_MJR 9
+#define TOOLS_VERSION_HOSTED14_TECHPREVIEW1_V_MNR 8
+#define TOOLS_VERSION_HOSTED14_TECHPREVIEW1_V_BASE 1
+
+#ifndef RC_INVOKED
+#define TOOLS_VERSION_HOSTED14_TECHPREVIEW2 TOOLS_VERSION_TO_UINT(TOOLS_VERSION_HOSTED14_TECHPREVIEW2_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_HOSTED14_TECHPREVIEW2_V_MJR 9
+#define TOOLS_VERSION_HOSTED14_TECHPREVIEW2_V_MNR 8
+#define TOOLS_VERSION_HOSTED14_TECHPREVIEW2_V_BASE 2
+
+#ifndef RC_INVOKED
+#define TOOLS_VERSION_FUSION70_RELEASE TOOLS_VERSION_TO_UINT(TOOLS_VERSION_FUSION70_RELEASE_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_FUSION70_RELEASE_V_MJR 9
+#define TOOLS_VERSION_FUSION70_RELEASE_V_MNR 8
+#define TOOLS_VERSION_FUSION70_RELEASE_V_BASE 3
+
+#ifndef RC_INVOKED
+#define TOOLS_VERSION_FUSION70_UPDATE1 TOOLS_VERSION_TO_UINT(TOOLS_VERSION_FUSION70_UPDATE1_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_FUSION70_UPDATE1_V_MJR 9
+#define TOOLS_VERSION_FUSION70_UPDATE1_V_MNR 8
+#define TOOLS_VERSION_FUSION70_UPDATE1_V_BASE 4
+
+#ifndef RC_INVOKED
+#define TOOLS_VERSION_HOSTED14_RELEASE TOOLS_VERSION_TO_UINT(TOOLS_VERSION_HOSTED14_RELEASE_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_HOSTED14_RELEASE_V_MJR 9
+#define TOOLS_VERSION_HOSTED14_RELEASE_V_MNR 9
+#define TOOLS_VERSION_HOSTED14_RELEASE_V_BASE 0
+
+#ifndef RC_INVOKED
+#define TOOLS_VERSION_HOSTED14_UPDATE1 TOOLS_VERSION_TO_UINT(TOOLS_VERSION_HOSTED14_UPDATE1_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_HOSTED14_UPDATE1_V_MJR 9
+#define TOOLS_VERSION_HOSTED14_UPDATE1_V_MNR 9
+#define TOOLS_VERSION_HOSTED14_UPDATE1_V_BASE 1
+
+#ifndef RC_INVOKED
+#define TOOLS_VERSION_HOSTED14_UPDATE2 TOOLS_VERSION_TO_UINT(TOOLS_VERSION_HOSTED14_UPDATE2_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_HOSTED14_UPDATE2_V_MJR 9
+#define TOOLS_VERSION_HOSTED14_UPDATE2_V_MNR 9
+#define TOOLS_VERSION_HOSTED14_UPDATE2_V_BASE 2
+
+#ifndef RC_INVOKED
#define TOOLS_VERSION_2015_RELEASE TOOLS_VERSION_TO_UINT(TOOLS_VERSION_2015_RELEASE_V)
#endif /* RC_INVOKED */
#define TOOLS_VERSION_2015_RELEASE_V_MJR 9
#define TOOLS_VERSION_2015_RELEASE_V_MNR 10
#define TOOLS_VERSION_2015_RELEASE_V_BASE 0
-#ifndef RC_INVOKED
-#define TOOLS_VERSION_2015_PATCH01 TOOLS_VERSION_TO_UINT(TOOLS_VERSION_2015_PATCH01_V)
-#endif /* RC_INVOKED */
-#define TOOLS_VERSION_2015_PATCH01_V_MJR 9
-#define TOOLS_VERSION_2015_PATCH01_V_MNR 10
-#define TOOLS_VERSION_2015_PATCH01_V_BASE 1
-
/*
* Patch01OVT - open-vm-tools release from vsphere60p01tools - 9.10.2
*/
@@ -1263,9 +1318,30 @@ TOOLS_VERSION_UINT_TO_COMPONENTS(const ToolsVersion toolsVersion, // IN
#define TOOLS_VERSION_2015_PATCH01OVT_V_MNR 10
#define TOOLS_VERSION_2015_PATCH01OVT_V_BASE 2
-#define TOOLS_VERSION_CURRENT TOOLS_VERSION_2015_PATCH01OVT
-#define TOOLS_VERSION_CURRENT_STR TOOLS_VERSION_TO_STR(TOOLS_VERSION_2015_PATCH01OVT)
-#define TOOLS_VERSION_CURRENT_CSV TOOLS_VERSION_TO_CSV(TOOLS_VERSION_2015_PATCH01OVT)
+#ifndef RC_INVOKED
+#define TOOLS_VERSION_TORQUE_WRENCH_FC TOOLS_VERSION_TO_UINT(TOOLS_VERSION_TORQUE_WRENCH_FC_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_TORQUE_WRENCH_FC_V_MJR 9
+#define TOOLS_VERSION_TORQUE_WRENCH_FC_V_MNR 12
+#define TOOLS_VERSION_TORQUE_WRENCH_FC_V_BASE 0
+
+#ifndef RC_INVOKED
+#define TOOLS_VERSION_TORQUE_WRENCH_RC TOOLS_VERSION_TO_UINT(TOOLS_VERSION_TORQUE_WRENCH_RC_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_TORQUE_WRENCH_RC_V_MJR 9
+#define TOOLS_VERSION_TORQUE_WRENCH_RC_V_MNR 12
+#define TOOLS_VERSION_TORQUE_WRENCH_RC_V_BASE 1
+
+#ifndef RC_INVOKED
+#define TOOLS_VERSION_TORQUE_WRENCH_RELEASE TOOLS_VERSION_TO_UINT(TOOLS_VERSION_TORQUE_WRENCH_RELEASE_V)
+#endif /* RC_INVOKED */
+#define TOOLS_VERSION_TORQUE_WRENCH_RELEASE_V_MJR 10
+#define TOOLS_VERSION_TORQUE_WRENCH_RELEASE_V_MNR 0
+#define TOOLS_VERSION_TORQUE_WRENCH_RELEASE_V_BASE 0
+
+#define TOOLS_VERSION_CURRENT TOOLS_VERSION_TORQUE_WRENCH_RELEASE
+#define TOOLS_VERSION_CURRENT_STR TOOLS_VERSION_TO_STR(TOOLS_VERSION_TORQUE_WRENCH_RELEASE)
+#define TOOLS_VERSION_CURRENT_CSV TOOLS_VERSION_TO_CSV(TOOLS_VERSION_TORQUE_WRENCH_RELEASE)
/*
* The extended Tools version is the current Tools version with the
diff --git a/open-vm-tools/lib/include/vmci_defs.h b/open-vm-tools/lib/include/vmci_defs.h
index 7a077e59..d8ba8b49 100644
--- a/open-vm-tools/lib/include/vmci_defs.h
+++ b/open-vm-tools/lib/include/vmci_defs.h
@@ -363,7 +363,11 @@ typedef uint32 VMCI_Event;
// this event has the Context payload type.
#define VMCI_EVENT_MEM_ACCESS_OFF 6 // Applicable to VMX and vmk. Same as
// above for the payload type.
-#define VMCI_EVENT_MAX 7
+#define VMCI_EVENT_GUEST_PAUSED 7 // Applicable to vmk. This event has the
+ // Context payload type.
+#define VMCI_EVENT_GUEST_UNPAUSED 8 // Applicable to vmk. Same as above for
+ // the payload type.
+#define VMCI_EVENT_MAX 9
/*
* Of the above events, a few are reserved for use in the VMX, and
@@ -383,7 +387,9 @@ typedef uint32 VMCI_Event;
#else // VMX86_SERVER
#define VMCI_EVENT_VALID(_event) (_event < VMCI_EVENT_MAX && \
_event != VMCI_EVENT_MEM_ACCESS_ON && \
- _event != VMCI_EVENT_MEM_ACCESS_OFF)
+ _event != VMCI_EVENT_MEM_ACCESS_OFF && \
+ _event != VMCI_EVENT_GUEST_PAUSED && \
+ _event != VMCI_EVENT_GUEST_UNPAUSED)
#endif // VMX86_SERVER
/* Reserved guest datagram resource ids. */
@@ -410,7 +416,7 @@ typedef uint32 VMCIPrivilegeFlags;
#define VMCI_PRIVILEGE_FLAG_RESTRICTED 0x01
#define VMCI_PRIVILEGE_FLAG_TRUSTED 0x02
#define VMCI_PRIVILEGE_ALL_FLAGS (VMCI_PRIVILEGE_FLAG_RESTRICTED | \
- VMCI_PRIVILEGE_FLAG_TRUSTED)
+ VMCI_PRIVILEGE_FLAG_TRUSTED)
#define VMCI_NO_PRIVILEGE_FLAGS 0x00
#define VMCI_DEFAULT_PROC_PRIVILEGE_FLAGS VMCI_NO_PRIVILEGE_FLAGS
#define VMCI_LEAST_PRIVILEGE_FLAGS VMCI_PRIVILEGE_FLAG_RESTRICTED
diff --git a/open-vm-tools/lib/include/vmsupport.h b/open-vm-tools/lib/include/vmsupport.h
index f689db1a..5582bc37 100644
--- a/open-vm-tools/lib/include/vmsupport.h
+++ b/open-vm-tools/lib/include/vmsupport.h
@@ -34,18 +34,12 @@
*/
typedef enum {
-/* vm-support script is not running */
- VMSUPPORT_NOT_RUNNING = 0,
-/* vm-support script is beginning */
- VMSUPPORT_BEGINNING = 1,
-/* vm-support script running in progress */
- VMSUPPORT_RUNNING = 2,
-/* vm-support script is ending */
- VMSUPPORT_ENDING = 3,
-/* vm-support script failed */
- VMSUPPORT_ERROR = 10,
-/* vm-support collection not supported */
- VMSUPPORT_UNKNOWN = 100
+ VMSUPPORT_NOT_RUNNING = 0, /* script is not running */
+ VMSUPPORT_BEGINNING = 1, /* script is beginning */
+ VMSUPPORT_RUNNING = 2, /* script running in progress */
+ VMSUPPORT_ENDING = 3, /* script is ending */
+ VMSUPPORT_ERROR = 10, /* script failed */
+ VMSUPPORT_UNKNOWN = 100 /* collection not supported */
} VMSupportStatus;
/*
@@ -55,7 +49,7 @@ typedef enum {
typedef enum {
VMSUPPORT_CMD_RESET = 0,
- VMSUPPORT_CMD_SET = 1
+ VMSUPPORT_CMD_SET = 1
} VMSupportCmd;
#define RPC_VMSUPPORT_START "vmsupport.start"
diff --git a/open-vm-tools/lib/include/vmware/guestrpc/capabilities.h b/open-vm-tools/lib/include/vmware/guestrpc/capabilities.h
index fc888124..b91a15ff 100644
--- a/open-vm-tools/lib/include/vmware/guestrpc/capabilities.h
+++ b/open-vm-tools/lib/include/vmware/guestrpc/capabilities.h
@@ -59,7 +59,7 @@ typedef enum {
GHI_CAP_SET_HANDLER = 14, // supports setting the handler for types/protocols
UNITY_CAP_STATUS_UNITY_ACTIVE = 15, // supports GuestRpc bits for Unity Status
GHI_CAP_SET_OUTLOOK_TEMP_FOLDER = 16, // supports setting the Outlook temp folder
- OBSOLETE_17 = 17, // 17 is obsolete, do not use
+ // 17 is obsolete, do not use
CAP_SET_TOPO_MODES = 18, // supports setting topology modes in video driver
GHI_CAP_TRAY_ICONS = 19, // supports ghi.guest.trayIcon commands
GHI_CAP_SET_FOCUSED_WINDOW = 20, // supports ghi.guest.setFocusedWindow
@@ -69,7 +69,7 @@ typedef enum {
CAP_AUTOUPGRADE_AT_SHUTDOWN = 24, // supports auto-upgrading tools at OS shutdown
GHI_CAP_AUTOLOGON = 25, // supports autologon
CAP_DESKTOP_AUTOLOCK = 26, // supports desktop autolock
- CAP_UPDATE_AGENT = 27, // supports guest update agent
+ // 27 is obsolete, do not use
HGFSU_CAP_MIRROR_DOWNLOADS = 28, // supports remapping GOS Downloads to HGFS
HGFSU_CAP_MIRROR_MOVIES = 29, // supports remapping GOS Movies to HGFS
GHI_CAP_TOGGLE_START_UI = 30, // supports showing/hiding the Start UI
@@ -99,20 +99,6 @@ typedef struct {
* vmdb schema, since these strings are used as vmdb keys.
*/
-/*
- * This table must be sorted such that it can be indexed using the
- * GuestCapabilities enum above. RPC calls pass the value, and the
- * handler code uses it as an index. In other words, the value of the
- * caps field at index i must be equal to i as well. This is because
- * the code that looks up entries in this table assume as much. It
- * also means we don't need the cap field, or, to justify its existence,
- * the lookup code should be converted to loop through the table and
- * return the entry where cap == the value passed in the RPC call.
- * Moral of the story, new entries always at the bottom of the table
- * and the cap field must be set to the offset in the array (and make
- * sure the enum in GuestCapabilities is also set to that offset).
- */
-
static GuestCapElem guestCapTable[] = {
{ UNITY_CAP_START_MENU, UNITY_CAP_VMDB_PATH, "startmenu" },
{ UNITY_CAP_VIRTUAL_DESK, UNITY_CAP_VMDB_PATH, "virtualdesk" },
@@ -133,7 +119,6 @@ static GuestCapElem guestCapTable[] = {
{ GHI_CAP_SET_HANDLER, GHI_CAP_VMDB_PATH, "setHandler" },
{ UNITY_CAP_STATUS_UNITY_ACTIVE, UNITY_CAP_VMDB_PATH, "unityActive" },
{ GHI_CAP_SET_OUTLOOK_TEMP_FOLDER, GHI_CAP_VMDB_PATH, "setOutlookTempFolder" },
- { OBSOLETE_17, NULL, NULL },
{ CAP_SET_TOPO_MODES, CAP_VMDB_PATH, "displayTopologyModesSet" },
{ GHI_CAP_TRAY_ICONS, GHI_CAP_VMDB_PATH, "trayIcons" },
{ GHI_CAP_SET_FOCUSED_WINDOW, GHI_CAP_VMDB_PATH, "setFocusedWindow"},
@@ -143,7 +128,6 @@ static GuestCapElem guestCapTable[] = {
{ CAP_AUTOUPGRADE_AT_SHUTDOWN, CAP_VMDB_PATH, "autoUpgradeAtShutdown"},
{ GHI_CAP_AUTOLOGON, GHI_CAP_VMDB_PATH, "autologon" },
{ CAP_DESKTOP_AUTOLOCK, CAP_VMDB_PATH, "desktopAutolock" },
- { CAP_UPDATE_AGENT, CAP_VMDB_PATH, "updateAgent"},
{ HGFSU_CAP_MIRROR_DOWNLOADS, HGFSU_CAP_VMDB_PATH, "mirrorDownloads" },
{ HGFSU_CAP_MIRROR_MOVIES, HGFSU_CAP_VMDB_PATH, "mirrorMovies" },
{ GHI_CAP_TOGGLE_START_UI, GHI_CAP_VMDB_PATH, "toggleStartUI"},
diff --git a/open-vm-tools/lib/include/vmware/guestrpc/timesync.h b/open-vm-tools/lib/include/vmware/guestrpc/timesync.h
index 415336c2..0b6e0530 100644
--- a/open-vm-tools/lib/include/vmware/guestrpc/timesync.h
+++ b/open-vm-tools/lib/include/vmware/guestrpc/timesync.h
@@ -28,6 +28,8 @@
#define TOOLSOPTION_SYNCTIME "synctime"
#define TOOLSOPTION_SYNCTIME_PERIOD "synctime.period"
#define TOOLSOPTION_SYNCTIME_ENABLE "time.synchronize.tools.enable"
+#define TOOLSOPTION_SYNCTIME_STARTUP_BACKWARD \
+ "time.synchronize.tools.startup.backward"
#define TOOLSOPTION_SYNCTIME_STARTUP "time.synchronize.tools.startup"
#define TOOLSOPTION_SYNCTIME_SLEWCORRECTION "time.synchronize.tools.slewCorrection"
#define TOOLSOPTION_SYNCTIME_PERCENTCORRECTION "time.synchronize.tools.percentCorrection"
diff --git a/open-vm-tools/lib/include/vmware/tools/log.h b/open-vm-tools/lib/include/vmware/tools/log.h
index 8c00d64c..d10ee8eb 100644
--- a/open-vm-tools/lib/include/vmware/tools/log.h
+++ b/open-vm-tools/lib/include/vmware/tools/log.h
@@ -66,6 +66,30 @@
* can also affect other running applications that need to send messages to the
* host. Do not use this logger unless explicitly instructed to do so.
*
+ * Log levels:
+ *
+ * glib log levels are supported. The error levels from
+ * most to least severe:
+ *
+ * 'error' - fatal errors
+ * 'critical' - critical errors
+ * 'warning' - something unexpected happened (useful when an error will
+ * be reported back.)
+ * 'message' - messages about services starting, version data
+ * 'info' - informational and diagnostic messages.
+ * 'debug' - debug messages, typically only of interest ot a developer
+ *
+ *
+ * Until vSphere 6.0, the default logging level for beta/rel is 'warning'.
+ * Since vsphere 6.0 it is 'message'.
+ *
+ * When adding new logging messages, be sure to use the appropriate
+ * level to balance the amount of logging and usability. The goal
+ * is to be able to debug a customer problem with the default log level
+ * whenever possible, while not filling up logfiles with noise
+ * or customer-sensitive data.
+ *
+ *
* Logging configuration should be under the "[logging]" group in the
* application's configuration file.
*
@@ -137,6 +161,14 @@
# define g_info(fmt, ...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, fmt, ## __VA_ARGS__)
#endif
+/** default logging level */
+#ifdef VMX86_DEBUG
+#define VMTOOLS_LOGGING_LEVEL_DEFAULT "info"
+#else
+#define VMTOOLS_LOGGING_LEVEL_DEFAULT "message"
+#endif
+
+
/*
*******************************************************************************
* vm_{critical,debug,error,info,message,warning} -- */ /**
diff --git a/open-vm-tools/lib/include/vmware/tools/plugin.h b/open-vm-tools/lib/include/vmware/tools/plugin.h
index be714fa2..915e2de7 100644
--- a/open-vm-tools/lib/include/vmware/tools/plugin.h
+++ b/open-vm-tools/lib/include/vmware/tools/plugin.h
@@ -68,6 +68,20 @@
g_source_attach(__src, g_main_loop_get_context((ctx)->mainLoop)); \
} while (0)
+/**
+ * Checks if the Tools service is main (system) service or not.
+ * @param[in] ctx The application context or tools service state.
+ */
+#define TOOLS_IS_MAIN_SERVICE(ctx) (strcmp((ctx)->name, \
+ VMTOOLS_GUEST_SERVICE) == 0)
+
+/**
+ * Checks if the Tools service is user (logged in user) service or not.
+ * @param[in] ctx The application context or tools service state.
+ */
+#define TOOLS_IS_USER_SERVICE(ctx) (strcmp((ctx)->name, \
+ VMTOOLS_USER_SERVICE) == 0)
+
/* Indentation levels for the state log function below. */
#define TOOLS_STATE_LOG_ROOT 0
#define TOOLS_STATE_LOG_CONTAINER 1
diff --git a/open-vm-tools/lib/include/vmware/tools/utils.h b/open-vm-tools/lib/include/vmware/tools/utils.h
index cee09cac..8c13f737 100644
--- a/open-vm-tools/lib/include/vmware/tools/utils.h
+++ b/open-vm-tools/lib/include/vmware/tools/utils.h
@@ -115,6 +115,12 @@ VMTools_WriteConfig(const gchar *path,
GKeyFile *config,
GError **err);
+gboolean
+VMTools_ChangeLogFilePath(const gchar *delimiter,
+ const gchar *appendString,
+ const gchar *domain,
+ GKeyFile *conf);
+
#if defined(G_PLATFORM_WIN32)
gboolean
@@ -143,11 +149,23 @@ void
VMTools_SetGuestSDKMode(void);
void
+VMTools_AcquireLogStateLock(void);
+
+void
+VMTools_ReleaseLogStateLock(void);
+
+void
VMTools_StopLogging(void);
void
VMTools_RestartLogging(void);
+void
+VMTools_SuspendLogIO(void);
+
+void
+VMTools_ResumeLogIO(void);
+
GArray *
VMTools_WrapArray(gconstpointer data,
guint elemSize,
diff --git a/open-vm-tools/lib/include/vthreadBase.h b/open-vm-tools/lib/include/vthreadBase.h
index 4339df1d..c83535c3 100644
--- a/open-vm-tools/lib/include/vthreadBase.h
+++ b/open-vm-tools/lib/include/vthreadBase.h
@@ -145,7 +145,6 @@ VThreadBase_IsInSignal(void)
#else
Bool VThreadBase_IsInSignal(void);
void VThreadBase_SetIsInSignal(VThreadID tid, Bool isInSignal);
-int VThreadBase_SigMask(int how, const sigset_t *newmask, sigset_t *oldmask);
#endif
#endif /* VMM */
diff --git a/open-vm-tools/lib/include/win32util.h b/open-vm-tools/lib/include/win32util.h
index 7c69212d..21e76ff9 100644
--- a/open-vm-tools/lib/include/win32util.h
+++ b/open-vm-tools/lib/include/win32util.h
@@ -47,12 +47,12 @@ typedef enum AutorunState {
/* Defines */
#define VMX_SHUTDOWN_ORDER 0x100 // Application reserved last shutdown range.
#define UI_SHUTDOWN_ORDER 0x300 // Application reserved first shutdown range.
-#define TOOLS_SHUTDOWN_ORDER 0x100 // Application reserved last shutdown range
+#define TOOLS_SHUTDOWN_ORDER 0x100 // Application reserved last shutdown range
/* Function declarations */
-Unicode W32Util_GetInstallPath(void);
-Unicode W32Util_GetInstallPath64(void);
+char * W32Util_GetInstallPath(void);
+char * W32Util_GetInstallPath64(void);
/*
* The string returned is allocated on the heap and must be freed by the
@@ -60,18 +60,18 @@ Unicode W32Util_GetInstallPath64(void);
*/
-Unicode W32Util_GetAppDataFilePath(ConstUnicode fileName);
-Unicode W32Util_GetLocalAppDataFilePath(ConstUnicode fileName);
+char *W32Util_GetAppDataFilePath(const char *fileName);
+char *W32Util_GetLocalAppDataFilePath(const char *fileName);
-Unicode W32Util_GetCommonAppDataFilePath(ConstUnicode fileName);
-Unicode W32Util_GetVmwareCommonAppDataFilePath(ConstUnicode fileName);
+char *W32Util_GetCommonAppDataFilePath(const char *fileName);
+char *W32Util_GetVmwareCommonAppDataFilePath(const char *fileName);
-Unicode W32Util_GetMyDocumentPath(void);
-Unicode W32Util_GetMyVideoPath(BOOL myDocumentsOnFail);
+char *W32Util_GetMyDocumentPath(void);
+char *W32Util_GetMyVideoPath(BOOL myDocumentsOnFail);
-Unicode W32Util_GetDefaultVMPath(ConstUnicode pref);
-Unicode W32Util_GetInstalledFilePath(ConstUnicode fileName);
-Unicode W32Util_GetInstalledFilePath64(ConstUnicode fileName);
+char *W32Util_GetDefaultVMPath(const char *pref);
+char *W32Util_GetInstalledFilePath(const char *fileName);
+char *W32Util_GetInstalledFilePath64(const char *fileName);
HKEY W32Util_OpenProductRegKey(REGSAM access);
HKEY W32Util_OpenUserRegKey(REGSAM access);
@@ -79,21 +79,21 @@ HKEY W32Util_OpenUserRegKey(REGSAM access);
LPTOP_LEVEL_EXCEPTION_FILTER W32Util_SetUnhandledExceptionFilter(void);
-Bool W32Util_CreateProcessArgv(ConstUnicode lpApplicationName,
- ConstUnicode *argv,
- LPSECURITY_ATTRIBUTES lpProcessAttributes,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- BOOL bInheritHandles,
- DWORD dwCreationFlags,
- LPVOID lpEnvironment,
- ConstUnicode lpCurrentDirectory,
- LPSTARTUPINFOA lpStartupInfo,
+Bool W32Util_CreateProcessArgv(const char *lpApplicationName,
+ const char **argv,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ const char *lpCurrentDirectory,
+ LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation);
void W32Util_SplitCommandLine(char *commandLine,
int maxArgs,
char *progName,
- int *argc,
+ int *argc,
char **argv);
BOOL W32Util_ReadFileTimeout(HANDLE hFile, // handle of file to read
@@ -105,29 +105,29 @@ BOOL W32Util_ReadFileTimeout(HANDLE hFile, // handle of file to r
BOOL W32Util_WriteFileTimeout(HANDLE hFile, // handle to file to write to
LPCVOID lpBuffer, // pointer to data to write to file
DWORD nNumberOfBytesToWrite, // number of bytes to write
- LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
+ LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
DWORD msTimeout); // timeout in milliseconds
-Unicode W32Util_RealPath(ConstUnicode path);
+char *W32Util_RealPath(const char *path);
BOOL W32Util_CheckForPrivilegeHeld(HANDLE token, LPCTSTR priv);
typedef BOOL (*SidFilterFunction)(PSID psid, void *cbData);
-BOOL W32Util_GetEffectiveRightsForName(ConstUnicode user,
- ConstUnicode path,
+BOOL W32Util_GetEffectiveRightsForName(const char *user,
+ const char *path,
DWORD *rights);
BOOL W32Util_GetEffectiveRightsForSid(PSID psid,
- ConstUnicode path,
+ const char *path,
DWORD *rights);
BOOL W32Util_ModifyRights(PSID psid,
- ConstUnicode path,
+ const char *path,
DWORD rights,
BOOL isAllow);
void W32Util_FreeSids(PSID *sidList);
-BOOL W32Util_GetMatchingSids(ConstUnicode path,
- PSID **psidList,
- SidFilterFunction matchCb,
+BOOL W32Util_GetMatchingSids(const char *path,
+ PSID **psidList,
+ SidFilterFunction matchCb,
void *cbData);
LPSTR W32Util_WideStrToAsciiStr(LPCWSTR wideStr);
@@ -139,23 +139,23 @@ BOOL W32Util_WinSockAddReference(void);
BOOL W32Util_WinSockDereference(void);
Bool W32Util_RegisterService(Bool bRegister,
- ConstUnicode name,
- ConstUnicode displayName,
- ConstUnicode description,
- ConstUnicode binaryPath,
- Unicode *errString);
+ const char *name,
+ const char *displayName,
+ const char *description,
+ const char *binaryPath,
+ char **errString);
-Bool W32Util_DebugService(ConstUnicode dbgFile);
+Bool W32Util_DebugService(const char *dbgFile);
-Bool W32Util_RegisterEventLog(ConstUnicode serviceName,
+Bool W32Util_RegisterEventLog(const char *serviceName,
Bool registryVolatile,
DWORD typesSupported,
- ConstUnicode eventMsgFile,
- ConstUnicode categoryMsgFile,
+ const char *eventMsgFile,
+ const char *categoryMsgFile,
DWORD categoryCount,
- ConstUnicode paramMsgFile);
+ const char *paramMsgFile);
-Bool W32Util_UnregisterEventLog(ConstUnicode serviceName);
+Bool W32Util_UnregisterEventLog(const char *serviceName);
typedef enum SetSDPrivsAccounts {
SDPRIV_GROUP_ADMIN = 0x1,
@@ -165,22 +165,22 @@ typedef enum SetSDPrivsAccounts {
Bool W32Util_SetSDPrivs(PSECURITY_DESCRIPTOR pSecurityDescriptor,
DWORD accessType, SetSDPrivsAccounts accounts,
- PACL *pAcl, Unicode *errString);
+ PACL *pAcl, char **errString);
BOOL W32Util_SetSecurityDescriptorW(PSECURITY_DESCRIPTOR pSecurityDescriptor,
- ConstUnicode Owner, PACL *pAcl);
+ const char *Owner, PACL *pAcl);
BOOL W32Util_SetSecurityDescriptorSid(PSECURITY_DESCRIPTOR sd, PSID sid,
PACL *pAcl);
BOOL W32Util_GetThreadHandle(HANDLE *handle);
-Bool W32Util_AccessCheck(HANDLE token,
- PSECURITY_DESCRIPTOR pSecurityDescriptor,
+Bool W32Util_AccessCheck(HANDLE token,
+ PSECURITY_DESCRIPTOR pSecurityDescriptor,
int desiredAccess);
-Bool W32Util_HasAccessToFile(ConstUnicode filename, ACCESS_MASK desiredAccess,
- HANDLE token);
+Bool W32Util_HasAccessToFile(const char *filename, ACCESS_MASK desiredAccess,
+ HANDLE token);
-Bool W32Util_GetSecurityDescriptor(ConstUnicode path,
+Bool W32Util_GetSecurityDescriptor(const char *path,
PSECURITY_DESCRIPTOR *ppSecurityDescriptor);
void W32Util_InitStdioConsole(void);
@@ -193,17 +193,17 @@ Bool W32Util_CreateWellKnownSid(WELL_KNOWN_SID_TYPE wsdType,
Bool W32Util_GetCurrentUserSid(PSID *pSid);
Bool W32Util_GetLocalAdminGroupSid(PSID *pSid);
Bool W32Util_GetVMwareGroupSid(PSID *pSid);
-Bool W32Util_MakeSafeDirectory(ConstUnicode path);
-Bool W32Util_IsDirectorySafe(ConstUnicode path);
-Bool W32Util_DoesVolumeSupportAcls(ConstUnicode path);
+Bool W32Util_MakeSafeDirectory(const char *path);
+Bool W32Util_IsDirectorySafe(const char *path);
+Bool W32Util_DoesVolumeSupportAcls(const char *path);
Bool W32Util_GetRegistryAutorun(AutorunState* state);
Bool W32Util_SetRegistryAutorun(const AutorunState state);
Bool W32Util_AllowAdminCOM(void);
-Unicode W32Util_GetAppDataPath(void);
-Unicode W32Util_RobustGetLongPath(ConstUnicode path);
+char * W32Util_GetAppDataPath(void);
+char * W32Util_RobustGetLongPath(const char *path);
typedef enum SecureObjectType {
SecureObject_Process,
@@ -219,11 +219,11 @@ HMODULE W32Util_GetModuleByAddress(const void *addr);
Bool W32Util_VerifyXPModeHostLicense(void);
-Unicode W32Util_GetPipeNameFromFilePath(ConstUnicode fileName);
+char * W32Util_GetPipeNameFromFilePath(const char *fileName);
Bool W32Util_CheckGroupMembership(HANDLE hToken,
BOOL respectUAC,
- Unicode *errString,
+ char * *errString,
BOOL *bMember);
Bool W32Util_DismountVolumes(uint16 drive,
diff --git a/open-vm-tools/lib/include/wiper.h b/open-vm-tools/lib/include/wiper.h
index ef2e0804..81d908f6 100644
--- a/open-vm-tools/lib/include/wiper.h
+++ b/open-vm-tools/lib/include/wiper.h
@@ -33,6 +33,7 @@
#include "vm_basic_types.h"
#include "dbllnklst.h"
+#define TOOLS_WIPE_CANCEL "Wipe cancelled by user.\n"
typedef enum {
PARTITION_UNSUPPORTED = 0,
diff --git a/open-vm-tools/lib/include/x86_basic_defs.h b/open-vm-tools/lib/include/x86_basic_defs.h
index 1d2e064e..b39cbe37 100644
--- a/open-vm-tools/lib/include/x86_basic_defs.h
+++ b/open-vm-tools/lib/include/x86_basic_defs.h
@@ -35,17 +35,6 @@
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
-#define SIZE_8BIT 1
-#define SIZE_16BIT 2
-#define SIZE_24BIT 3
-#define SIZE_32BIT 4
-#define SIZE_48BIT 6
-#define SIZE_64BIT 8
-#define SIZE_80BIT 10
-#define SIZE_128BIT 16
-#define SIZE_256BIT 32
-
-
#define X86_MAX_INSTR_LEN 15 /* Max byte length of an x86 instruction. */
#define NUM_IDT_VECTORS 256
diff --git a/open-vm-tools/lib/include/x86cpuid.h b/open-vm-tools/lib/include/x86cpuid.h
index 52871cc4..161a8acd 100644
--- a/open-vm-tools/lib/include/x86cpuid.h
+++ b/open-vm-tools/lib/include/x86cpuid.h
@@ -124,6 +124,7 @@ CPUIDQuery;
CPUIDLEVEL(FALSE, A, 0xA, 0) \
CPUIDLEVEL(FALSE, B, 0xB, 2) \
CPUIDLEVEL(TRUE, D, 0xD, 4) \
+ CPUIDLEVEL(FALSE, 12, 0x12, 4) \
CPUIDLEVEL(FALSE, 400, 0x40000000, 0) \
CPUIDLEVEL(FALSE, 401, 0x40000001, 0) \
CPUIDLEVEL(FALSE, 402, 0x40000002, 0) \
@@ -287,14 +288,14 @@ typedef enum {
} CpuidFieldSupported;
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_0 \
+#define CPUID_FIELD_DATA_LEVEL_0 \
FIELD( 0, 0, EAX, 0, 32, NUMLEVELS, ANY, FALSE) \
FIELD( 0, 0, EBX, 0, 32, VENDOR1, YES, TRUE) \
FIELD( 0, 0, ECX, 0, 32, VENDOR3, YES, TRUE) \
FIELD( 0, 0, EDX, 0, 32, VENDOR2, YES, TRUE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_1 \
+#define CPUID_FIELD_DATA_LEVEL_1 \
FIELD( 1, 0, EAX, 0, 4, STEPPING, ANY, FALSE) \
FIELD( 1, 0, EAX, 4, 4, MODEL, ANY, FALSE) \
FIELD( 1, 0, EAX, 8, 4, FAMILY, YES, FALSE) \
@@ -387,7 +388,7 @@ FIELD( 2, 0, EDX, 16, 8, LEAF2_CACHE14, NA, FALSE) \
FIELD( 2, 0, EDX, 24, 8, LEAF2_CACHE15, NA, FALSE) \
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_4 \
+#define CPUID_FIELD_DATA_LEVEL_4 \
FIELD( 4, 0, EAX, 0, 5, LEAF4_CACHE_TYPE, NA, FALSE) \
FIELD( 4, 0, EAX, 5, 3, LEAF4_CACHE_LEVEL, NA, FALSE) \
FLAG( 4, 0, EAX, 8, 1, LEAF4_CACHE_SELF_INIT, NA, FALSE) \
@@ -403,7 +404,7 @@ FLAG( 4, 0, EDX, 1, 1, LEAF4_CACHE_IS_INCLUSIVE, NA, FALSE) \
FLAG( 4, 0, EDX, 2, 1, LEAF4_CACHE_COMPLEX_INDEXING, NA, FALSE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_5 \
+#define CPUID_FIELD_DATA_LEVEL_5 \
FIELD( 5, 0, EAX, 0, 16, MWAIT_MIN_SIZE, NA, FALSE) \
FIELD( 5, 0, EBX, 0, 16, MWAIT_MAX_SIZE, NA, FALSE) \
FLAG( 5, 0, ECX, 0, 1, MWAIT_EXTENSIONS, NA, FALSE) \
@@ -415,7 +416,7 @@ FIELD( 5, 0, EDX, 12, 4, MWAIT_C3_SUBSTATE, NA, FALSE) \
FIELD( 5, 0, EDX, 16, 4, MWAIT_C4_SUBSTATE, NA, FALSE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_6 \
+#define CPUID_FIELD_DATA_LEVEL_6 \
FLAG( 6, 0, EAX, 0, 1, THERMAL_SENSOR, NA, FALSE) \
FLAG( 6, 0, EAX, 1, 1, TURBO_MODE, NA, FALSE) \
FLAG( 6, 0, EAX, 2, 1, APIC_INVARIANT, NA, FALSE) \
@@ -434,10 +435,11 @@ FLAG( 6, 0, ECX, 3, 1, ENERGY_PERF_BIAS, NA, FALSE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_7 \
+#define CPUID_FIELD_DATA_LEVEL_7 \
FLAG( 7, 0, EBX, 0, 1, FSGSBASE, YES, FALSE) \
FLAG( 7, 0, EBX, 1, 1, TSC_ADJUST, ANY, FALSE) \
FLAG( 7, 0, EBX, 3, 1, BMI1, YES, TRUE) \
+FLAG( 7, 0, EBX, 2, 1, SGX, NO, FALSE) \
FLAG( 7, 0, EBX, 4, 1, HLE, YES, TRUE) \
FLAG( 7, 0, EBX, 5, 1, AVX2, YES, TRUE) \
FLAG( 7, 0, EBX, 7, 1, SMEP, YES, FALSE) \
@@ -450,11 +452,13 @@ FLAG( 7, 0, EBX, 13, 1, FP_SEGMENT_ZERO, ANY, TRUE) \
FLAG( 7, 0, EBX, 15, 1, PQE, NO, FALSE) \
FLAG( 7, 0, EBX, 18, 1, RDSEED, YES, TRUE) \
FLAG( 7, 0, EBX, 19, 1, ADX, YES, TRUE) \
-FLAG( 7, 0, EBX, 20, 1, SMAP, YES, FALSE)
+FLAG( 7, 0, EBX, 20, 1, SMAP, YES, FALSE) \
+FLAG( 7, 0, EBX, 25, 1, PT, NO, FALSE) \
+FLAG( 7, 0, ECX, 0, 1, PREFETCHWT1, NO, TRUE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_A \
+#define CPUID_FIELD_DATA_LEVEL_A \
FIELD( A, 0, EAX, 0, 8, PMC_VERSION, NA, FALSE) \
FIELD( A, 0, EAX, 8, 8, PMC_NUM_GEN, NA, FALSE) \
FIELD( A, 0, EAX, 16, 8, PMC_WIDTH_GEN, NA, FALSE) \
@@ -470,7 +474,7 @@ FIELD( A, 0, EDX, 0, 5, PMC_NUM_FIXED, NA, FALSE) \
FIELD( A, 0, EDX, 5, 8, PMC_WIDTH_FIXED, NA, FALSE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_B \
+#define CPUID_FIELD_DATA_LEVEL_B \
FIELD( B, 0, EAX, 0, 5, TOPOLOGY_MASK_WIDTH, NA, FALSE) \
FIELD( B, 0, EBX, 0, 16, TOPOLOGY_CPUS_SHARING_LEVEL, NA, FALSE) \
FIELD( B, 0, ECX, 0, 8, TOPOLOGY_LEVEL_NUMBER, NA, FALSE) \
@@ -478,7 +482,7 @@ FIELD( B, 0, ECX, 8, 8, TOPOLOGY_LEVEL_TYPE, NA, FALSE) \
FIELD( B, 0, EDX, 0, 32, TOPOLOGY_X2APIC_ID, NA, FALSE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_D \
+#define CPUID_FIELD_DATA_LEVEL_D \
FLAG( D, 0, EAX, 0, 1, XCR0_MASTER_LEGACY_FP, YES, FALSE) \
FLAG( D, 0, EAX, 1, 1, XCR0_MASTER_SSE, YES, FALSE) \
FLAG( D, 0, EAX, 2, 1, XCR0_MASTER_YMM_H, YES, FALSE) \
@@ -506,26 +510,138 @@ FIELD( D, 62, EDX, 0, 32, XSAVE_LWP_RSVD2, NO, FALSE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_400 \
-FIELD(400, 0, EAX, 0, 32, NUM_HYP_LEVELS, NA, FALSE) \
-FIELD(400, 0, EBX, 0, 32, HYPERVISOR1, NA, FALSE) \
-FIELD(400, 0, ECX, 0, 32, HYPERVISOR2, NA, FALSE) \
-FIELD(400, 0, EDX, 0, 32, HYPERVISOR3, NA, FALSE)
+#define CPUID_FIELD_DATA_LEVEL_12 \
+FLAG( 12, 0, EAX, 0, 1, SGX1, NA, FALSE) \
+FLAG( 12, 0, EAX, 1, 1, SGX2, NA, FALSE) \
+FLAG( 12, 0, EBX, 31, 1, SGX_MISCSELECT, NA, FALSE) \
+FIELD( 12, 0, EDX, 0, 8, MAX_ENCLAVE_SIZE_NOT64, NA, FALSE) \
+FIELD( 12, 0, EDX, 8, 8, MAX_ENCLAVE_SIZE_64, NA, FALSE) \
+FIELD( 12, 1, EAX, 0, 32, SECS_ATTRIBUTES0, NA, FALSE) \
+FIELD( 12, 1, EBX, 0, 32, SECS_ATTRIBUTES1, NA, FALSE) \
+FIELD( 12, 1, ECX, 0, 32, SECS_ATTRIBUTES2, NA, FALSE) \
+FIELD( 12, 1, EDX, 0, 32, SECS_ATTRIBUTES3, NA, FALSE) \
+FIELD( 12, 2, EAX, 0, 4, EPC00_VALID, NA, FALSE) \
+FIELD( 12, 2, EAX, 12, 20, EPC00_BASE_LOW, NA, FALSE) \
+FIELD( 12, 2, EBX, 0, 20, EPC00_BASE_HIGH, NA, FALSE) \
+FIELD( 12, 2, ECX, 0, 4, EPC00_PROTECTED, NA, FALSE) \
+FIELD( 12, 2, ECX, 12, 20, EPC00_SIZE_LOW, NA, FALSE) \
+FIELD( 12, 2, EDX, 0, 20, EPC00_SIZE_HIGH, NA, FALSE) \
+FIELD( 12, 3, EAX, 0, 4, EPC01_VALID, NA, FALSE) \
+FIELD( 12, 3, EAX, 12, 20, EPC01_BASE_LOW, NA, FALSE) \
+FIELD( 12, 3, EBX, 0, 20, EPC01_BASE_HIGH, NA, FALSE) \
+FIELD( 12, 3, ECX, 0, 4, EPC01_PROTECTED, NA, FALSE) \
+FIELD( 12, 3, ECX, 12, 20, EPC01_SIZE_LOW, NA, FALSE) \
+FIELD( 12, 3, EDX, 0, 20, EPC01_SIZE_HIGH, NA, FALSE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_410 \
+#define CPUID_FIELD_DATA_LEVEL_400 \
+FIELD(400, 0, EAX, 0, 32, MAX_HYP_LEVEL, NA, FALSE) \
+FIELD(400, 0, EBX, 0, 32, HYPERVISOR_VENDOR0, NA, FALSE) \
+FIELD(400, 0, ECX, 0, 32, HYPERVISOR_VENDOR1, NA, FALSE) \
+FIELD(400, 0, EDX, 0, 32, HYPERVISOR_VENDOR2, NA, FALSE)
+
+/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
+#define CPUID_FIELD_DATA_LEVEL_401 \
+FIELD(401, 0, EAX, 0, 32, HV_INTERFACE_SIGNATURE, NA, FALSE)
+
+/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
+#define CPUID_FIELD_DATA_LEVEL_402 \
+FIELD(402, 0, EAX, 0, 32, BUILD_NUMBER, NA, FALSE) \
+FIELD(402, 0, EBX, 0, 16, MINOR_VERSION, NA, FALSE) \
+FIELD(402, 0, EBX, 16, 16, MAJOR_VERSION, NA, FALSE) \
+FIELD(402, 0, ECX, 0, 32, SERVICE_PACK, NA, FALSE) \
+FIELD(402, 0, EDX, 0, 24, SERVICE_NUMBER, NA, FALSE) \
+FIELD(402, 0, EDX, 24, 8, SERVICE_BRANCH, NA, FALSE)
+
+/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
+#define CPUID_FIELD_DATA_LEVEL_403 \
+FLAG( 403, 0, EAX, 0, 1, VP_RUNTIME_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 1, 1, REF_COUNTER_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 2, 1, BASIC_SYNIC_MSRS_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 3, 1, SYNTH_TIMER_MSRS_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 4, 1, APIC_ACCESS_MSRS_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 5, 1, HYPERCALL_MSRS_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 6, 1, VP_INDEX_MSR_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 7, 1, VIRT_RESET_MSR_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 8, 1, STATS_PAGES_MSRS_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 9, 1, REF_TSC_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 10, 1, GUEST_IDLE_MSR_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 11, 1, FREQUENCY_MSRS_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EAX, 12, 1, SYNTH_DEBUG_MSRS_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EBX, 0, 1, CREATE_PARTITIONS_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 1, 1, ACCESS_PARTITION_ID_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 2, 1, ACCESS_MEMORY_POOL_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 3, 1, ADJUST_MESSAGE_BUFFERS_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 4, 1, POST_MESSAGES_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 5, 1, SIGNAL_EVENTS_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 6, 1, CREATE_PORT_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 7, 1, CONNECT_PORT_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 8, 1, ACCESS_STATS_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 11, 1, DEBUGGING_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 12, 1, CPU_MANAGEMENT_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 13, 1, CONFIGURE_PROFILER_FLAG, NA, FALSE) \
+FLAG( 403, 0, EBX, 14, 1, ENABLE_EXPANDED_STACKWALKING_FLAG, NA, FALSE) \
+FIELD(403, 0, ECX, 0, 4, MAX_POWER_STATE, NA, FALSE) \
+FLAG( 403, 0, ECX, 4, 1, HPET_NEEDED_FOR_C3, NA, FALSE) \
+FLAG( 403, 0, EDX, 0, 1, MWAIT_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 1, 1, GUEST_DEBUGGING_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 2, 1, PERFORMANCE_MONITOR_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 3, 1, CPU_DYN_PARTITIONING_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 4, 1, XMM_REGISTERS_FOR_HYPERCALL_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 5, 1, GUEST_IDLE_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 6, 1, HYPERVISOR_SLEEP_STATE_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 7, 1, NUMA_DISTANCE_QUERY_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 8, 1, TIMER_FREQUENCY_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 9, 1, SYNTH_MACHINE_CHECK_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 10, 1, GUEST_CRASH_MSRS_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 11, 1, DEBUG_MSRS_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 12, 1, NPIEP1_AVAIL, NA, FALSE) \
+FLAG( 403, 0, EDX, 13, 1, DISABLE_HYPERVISOR_AVAIL, NA, FALSE)
+
+/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
+#define CPUID_FIELD_DATA_LEVEL_404 \
+FLAG( 404, 0, EAX, 0, 1, USE_HYPERCALL_TO_SWITCH_ADDR_SPACE, NA, FALSE) \
+FLAG( 404, 0, EAX, 1, 1, USE_HYPERCALL_TO_FLUSH_TLB, NA, FALSE) \
+FLAG( 404, 0, EAX, 2, 1, USE_HYPERCALL_FOR_TLB_SHOOTDOWN, NA, FALSE) \
+FLAG( 404, 0, EAX, 3, 1, USE_MSRS_FOR_EOI_ICR_TPR, NA, FALSE) \
+FLAG( 404, 0, EAX, 4, 1, USE_MSR_FOR_RESET, NA, FALSE) \
+FLAG( 404, 0, EAX, 5, 1, USE_RELAXED_TIMING, NA, FALSE) \
+FLAG( 404, 0, EAX, 6, 1, USE_DMA_REMAPPING, NA, FALSE) \
+FLAG( 404, 0, EAX, 7, 1, USE_INTERRUPT_REMAPPING, NA, FALSE) \
+FLAG( 404, 0, EAX, 8, 1, USE_X2APIC, NA, FALSE) \
+FLAG( 404, 0, EAX, 9, 1, DEPRECATE_AUTOEOI, NA, FALSE) \
+FIELD(404, 0, EBX, 0, 32, SPINLOCK_RETRIES, NA, FALSE)
+
+/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
+#define CPUID_FIELD_DATA_LEVEL_405 \
+FIELD(405, 0, EAX, 0, 32, MAX_VCPU, NA, FALSE) \
+FIELD(405, 0, EBX, 0, 32, MAX_LCPU, NA, FALSE) \
+FIELD(405, 0, ECX, 0, 32, MAX_REMAPPABLE_VECTORS, NA, FALSE)
+
+/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
+#define CPUID_FIELD_DATA_LEVEL_406 \
+FLAG( 406, 0, EAX, 0, 1, APIC_OVERLAY_ASSIST, NA, FALSE) \
+FLAG( 406, 0, EAX, 1, 1, MSR_BITMAPS, NA, FALSE) \
+FLAG( 406, 0, EAX, 2, 1, ARCH_PMCS, NA, FALSE) \
+FLAG( 406, 0, EAX, 3, 1, SLAT, NA, FALSE) \
+FLAG( 406, 0, EAX, 4, 1, DMA_REMAPPING, NA, FALSE) \
+FLAG( 406, 0, EAX, 5, 1, INTERRUPT_REMAPPING, NA, FALSE) \
+FLAG( 406, 0, EAX, 6, 1, MEMORY_PATROL_SCRUBBER, NA, FALSE)
+
+/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
+#define CPUID_FIELD_DATA_LEVEL_410 \
FIELD(410, 0, EAX, 0, 32, TSC_HZ, NA, FALSE) \
FIELD(410, 0, EBX, 0, 32, ACPIBUS_HZ, NA, FALSE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_80 \
+#define CPUID_FIELD_DATA_LEVEL_80 \
FIELD( 80, 0, EAX, 0, 32, NUM_EXT_LEVELS, NA, FALSE) \
FIELD( 80, 0, EBX, 0, 32, LEAF80_VENDOR1, NA, FALSE) \
FIELD( 80, 0, ECX, 0, 32, LEAF80_VENDOR3, NA, FALSE) \
FIELD( 80, 0, EDX, 0, 32, LEAF80_VENDOR2, NA, FALSE)
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_81 \
+#define CPUID_FIELD_DATA_LEVEL_81 \
FIELD( 81, 0, EAX, 0, 32, UNKNOWN81EAX, ANY, FALSE) \
FIELD( 81, 0, EAX, 0, 4, LEAF81_STEPPING, ANY, FALSE) \
FIELD( 81, 0, EAX, 4, 4, LEAF81_MODEL, ANY, FALSE) \
@@ -612,7 +728,7 @@ FLAG( 8A, 0, EDX, 11, 1, SVMEDX_RSVD1, NO, FALSE)
FIELD( 8A, 0, EDX, 14, 18, SVMEDX_RSVD2, NO, FALSE)
/* LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_8x \
+#define CPUID_FIELD_DATA_LEVEL_8x \
FIELD( 85, 0, EAX, 0, 8, ITLB_ENTRIES_2M4M_PGS, NA, FALSE) \
FIELD( 85, 0, EAX, 8, 8, ITLB_ASSOC_2M4M_PGS, NA, FALSE) \
FIELD( 85, 0, EAX, 16, 8, DTLB_ENTRIES_2M4M_PGS, NA, FALSE) \
@@ -681,7 +797,7 @@ FLAG( 8A, 0, EDX, 13, 1, SVM_AVIC, NO, FALSE) \
CPUID_8A_EDX_14_31
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
-#define CPUID_FIELD_DATA_LEVEL_81x \
+#define CPUID_FIELD_DATA_LEVEL_81x \
FIELD(819, 0, EAX, 0, 12, L1_ITLB_ENTRIES_1G_PGS, NA, FALSE) \
FIELD(819, 0, EAX, 12, 4, L1_ITLB_ASSOC_1G_PGS, NA, FALSE) \
FIELD(819, 0, EAX, 16, 12, L1_DTLB_ENTRIES_1G_PGS, NA, FALSE) \
@@ -761,7 +877,14 @@ FIELD(81E, 0, ECX, 8, 3, NODES_PER_PKG, NA, FALSE)
CPUID_FIELD_DATA_LEVEL_A \
CPUID_FIELD_DATA_LEVEL_B \
CPUID_FIELD_DATA_LEVEL_D \
+ CPUID_FIELD_DATA_LEVEL_12 \
CPUID_FIELD_DATA_LEVEL_400 \
+ CPUID_FIELD_DATA_LEVEL_401 \
+ CPUID_FIELD_DATA_LEVEL_402 \
+ CPUID_FIELD_DATA_LEVEL_403 \
+ CPUID_FIELD_DATA_LEVEL_404 \
+ CPUID_FIELD_DATA_LEVEL_405 \
+ CPUID_FIELD_DATA_LEVEL_406 \
CPUID_FIELD_DATA_LEVEL_410 \
CPUID_FIELD_DATA_LEVEL_80 \
CPUID_FIELD_DATA_LEVEL_81 \
@@ -996,17 +1119,17 @@ CPUIDCheck(int32 eaxIn, int32 eaxInCheck,
#define CPUID_FAMILY_P4 15
/* Effective AMD CPU Families */
-#define CPUID_FAMILY_5x86 4
-#define CPUID_FAMILY_K5 5
-#define CPUID_FAMILY_K6 5
-#define CPUID_FAMILY_K7 6
-#define CPUID_FAMILY_K8 15
-#define CPUID_FAMILY_K8L 16
-#define CPUID_FAMILY_K8MOBILE 17
-#define CPUID_FAMILY_LLANO 18
-#define CPUID_FAMILY_BOBCAT 20
-#define CPUID_FAMILY_BULLDOZER 21 // Bulldozer Piledriver Steamroller
-#define CPUID_FAMILY_KYOTO 22
+#define CPUID_FAMILY_5x86 0x4
+#define CPUID_FAMILY_K5 0x5
+#define CPUID_FAMILY_K6 0x5
+#define CPUID_FAMILY_K7 0x6
+#define CPUID_FAMILY_K8 0xf
+#define CPUID_FAMILY_K8L 0x10
+#define CPUID_FAMILY_K8MOBILE 0x11
+#define CPUID_FAMILY_LLANO 0x12
+#define CPUID_FAMILY_BOBCAT 0x14
+#define CPUID_FAMILY_BULLDOZER 0x15 // Bulldozer Piledriver Steamroller
+#define CPUID_FAMILY_KYOTO 0x16 // Note: Jaguar microarch
/* Effective VIA CPU Families */
#define CPUID_FAMILY_C7 6
@@ -1030,23 +1153,30 @@ CPUIDCheck(int32 eaxIn, int32 eaxInCheck,
#define CPUID_MODEL_ATOM_26 0x26 // Lincroft
#define CPUID_MODEL_ATOM_27 0x27 // Saltwell
#define CPUID_MODEL_SANDYBRIDGE_2A 0x2a // Sandybridge (desktop/mobile)
-#define CPUID_MODEL_SANDYBRIDGE_2D 0x2d // Sandybridge-EP
#define CPUID_MODEL_NEHALEM_2C 0x2c // Westmere-EP
+#define CPUID_MODEL_SANDYBRIDGE_2D 0x2d // Sandybridge-EP
#define CPUID_MODEL_NEHALEM_2E 0x2e // Nehalem-EX
#define CPUID_MODEL_NEHALEM_2F 0x2f // Westmere-EX
#define CPUID_MODEL_ATOM_35 0x35 // Cloverview
#define CPUID_MODEL_ATOM_36 0x36 // Cedarview
#define CPUID_MODEL_ATOM_37 0x37 // Bay Trail
#define CPUID_MODEL_SANDYBRIDGE_3A 0x3a // Ivy Bridge
-#define CPUID_MODEL_SANDYBRIDGE_3E 0x3e // Ivy Bridge-EP
#define CPUID_MODEL_HASWELL_3C 0x3c // Haswell DT
+#define CPUID_MODEL_BROADWELL_3D 0x3d // Broadwell-Ult
+#define CPUID_MODEL_SANDYBRIDGE_3E 0x3e // Ivy Bridge-EP
+#define CPUID_MODEL_HASWELL_3F 0x3f // Haswell EP/EN/EX
#define CPUID_MODEL_HASWELL_45 0x45 // Haswell Ultrathin
#define CPUID_MODEL_HASWELL_46 0x46 // Haswell (Crystal Well)
+#define CPUID_MODEL_BROADWELL_47 0x47 // Broadwell (Denlow)
#define CPUID_MODEL_ATOM_4A 0x4a // Future Silvermont
+#define CPUID_MODEL_ATOM_4C 0x4c // Airmont
#define CPUID_MODEL_ATOM_4D 0x4d // Avoton
+#define CPUID_MODEL_SKYLAKE_4E 0x4e // Skylake-Y
+#define CPUID_MODEL_BROADWELL_4F 0x4f // Broadwell EP/EN/EX
+#define CPUID_MODEL_BROADWELL_56 0x56 // Broadwell DE
#define CPUID_MODEL_ATOM_5A 0x5a // Future Silvermont
#define CPUID_MODEL_ATOM_5D 0x5d // Future Silvermont
-
+#define CPUID_MODEL_SKYLAKE_5E 0x5e // Skylake-S
#define CPUID_MODEL_PIII_07 7
#define CPUID_MODEL_PIII_08 8
@@ -1223,17 +1353,60 @@ CPUID_UARCH_IS_SANDYBRIDGE(uint32 v) // IN: %eax from CPUID with %eax=1.
static INLINE Bool
-CPUID_UARCH_IS_HASWELL(uint32 v) // IN: %eax from CPUID with %eax=1.
+CPUID_MODEL_IS_BROADWELL(uint32 v) // IN: %eax from CPUID with %eax=1.
{
/* Assumes the CPU manufacturer is Intel. */
uint32 effectiveModel = CPUID_EFFECTIVE_MODEL(v);
return CPUID_FAMILY_IS_P6(v) &&
- (effectiveModel == CPUID_MODEL_HASWELL_3C ||
- effectiveModel == CPUID_MODEL_HASWELL_45 ||
+ (effectiveModel == CPUID_MODEL_BROADWELL_3D ||
+ effectiveModel == CPUID_MODEL_BROADWELL_47 ||
+ effectiveModel == CPUID_MODEL_BROADWELL_4F ||
+ effectiveModel == CPUID_MODEL_BROADWELL_56);
+}
+
+
+static INLINE Bool
+CPUID_MODEL_IS_HASWELL(uint32 v) // IN: %eax from CPUID with %eax=1.
+{
+ /* Assumes the CPU manufacturer is Intel. */
+ uint32 effectiveModel = CPUID_EFFECTIVE_MODEL(v);
+
+ return CPUID_FAMILY_IS_P6(v) &&
+ (effectiveModel == CPUID_MODEL_HASWELL_3C ||
+ effectiveModel == CPUID_MODEL_HASWELL_3F ||
+ effectiveModel == CPUID_MODEL_HASWELL_45 ||
effectiveModel == CPUID_MODEL_HASWELL_46);
}
+
+static INLINE Bool
+CPUID_MODEL_IS_SKYLAKE(uint32 v) // IN: %eax from CPUID with %eax=1.
+{
+ /* Assumes the CPU manufacturer is Intel. */
+ return CPUID_FAMILY_IS_P6(v) &&
+ (CPUID_EFFECTIVE_MODEL(v) == CPUID_MODEL_SKYLAKE_5E ||
+ CPUID_EFFECTIVE_MODEL(v) == CPUID_MODEL_SKYLAKE_4E);
+}
+
+
+static INLINE Bool
+CPUID_UARCH_IS_SKYLAKE(uint32 v) // IN: %eax from CPUID with %eax=1.
+{
+ /* Assumes the CPU manufacturer is Intel. */
+ return CPUID_FAMILY_IS_P6(v) && CPUID_MODEL_IS_SKYLAKE(v);
+}
+
+
+static INLINE Bool
+CPUID_UARCH_IS_HASWELL(uint32 v) // IN: %eax from CPUID with %eax=1.
+{
+ /* Assumes the CPU manufacturer is Intel. */
+ return CPUID_FAMILY_IS_P6(v) &&
+ (CPUID_MODEL_IS_BROADWELL(v) || CPUID_MODEL_IS_HASWELL(v));
+}
+
+
static INLINE Bool
CPUID_MODEL_IS_CENTERTON(uint32 v) // IN: %eax from CPUID with %eax=1.
{
@@ -1288,21 +1461,6 @@ CPUID_MODEL_IS_IVYBRIDGE(uint32 v) // IN: %eax from CPUID with %eax=1.
static INLINE Bool
-CPUID_MODEL_IS_HASWELL(uint32 v) // IN: %eax from CPUID with %eax=1.
-{
- /* Assumes the CPU manufacturer is Intel. */
- uint32 effectiveModel = CPUID_EFFECTIVE_MODEL(v);
-
- return CPUID_FAMILY_IS_P6(v) &&
- (effectiveModel == CPUID_MODEL_HASWELL_3C ||
- effectiveModel == CPUID_MODEL_HASWELL_45 ||
- effectiveModel == CPUID_MODEL_HASWELL_46);
-}
-
-
-
-
-static INLINE Bool
CPUID_FAMILY_IS_K7(uint32 eax)
{
return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_K7;
@@ -1629,9 +1787,11 @@ static INLINE Bool
CPUID_SupportsMsrPlatformInfo(CpuidVendor vendor, uint32 version)
{
return vendor == CPUID_VENDOR_INTEL &&
- (CPUID_UARCH_IS_NEHALEM(version) ||
- CPUID_UARCH_IS_HASWELL(version) ||
- CPUID_UARCH_IS_SANDYBRIDGE(version));
+ (CPUID_UARCH_IS_NEHALEM(version) ||
+ CPUID_UARCH_IS_SANDYBRIDGE(version) ||
+ CPUID_UARCH_IS_HASWELL(version) ||
+ CPUID_UARCH_IS_SKYLAKE(version) ||
+ CPUID_MODEL_IS_AVOTON(version));
}
#endif
diff --git a/open-vm-tools/lib/include/x86cpuid_asm.h b/open-vm-tools/lib/include/x86cpuid_asm.h
index 4a713859..02a351cb 100644
--- a/open-vm-tools/lib/include/x86cpuid_asm.h
+++ b/open-vm-tools/lib/include/x86cpuid_asm.h
@@ -445,12 +445,6 @@ __GET_EAX_FROM_CPUID4(int inputEcx)
#define CPUID_FOR_SIDE_EFFECTS() ((void)__GET_EAX_FROM_CPUID(0))
-static INLINE void
-__GET_CPUID4(int inputEcx, CPUIDRegs *regs)
-{
- __GET_CPUID2(4, inputEcx, regs);
-}
-
/* The first parameter is used as an rvalue and then as an lvalue. */
#define GET_CPUID(_ax, _bx, _cx, _dx) { \
CPUIDRegs regs; \
diff --git a/open-vm-tools/lib/lock/ul.c b/open-vm-tools/lib/lock/ul.c
index 98af2e13..61f4bc01 100644
--- a/open-vm-tools/lib/lock/ul.c
+++ b/open-vm-tools/lib/lock/ul.c
@@ -26,6 +26,7 @@
#include "random.h"
static Bool mxInPanic = FALSE; // track when involved in a panic
+static Bool mxUserCollectLockingTree = FALSE;
Bool (*MXUserTryAcquireForceFail)() = NULL;
@@ -35,10 +36,58 @@ void (*MXUserMX_LockRec)(struct MX_MutexRec *lock) = NULL;
void (*MXUserMX_UnlockRec)(struct MX_MutexRec *lock) = NULL;
Bool (*MXUserMX_TryLockRec)(struct MX_MutexRec *lock) = NULL;
Bool (*MXUserMX_IsLockedByCurThreadRec)(const struct MX_MutexRec *lock) = NULL;
+char *(*MXUserMX_NameRec)(const struct MX_MutexRec *lock) = NULL;
static void (*MXUserMX_SetInPanic)(void) = NULL;
static Bool (*MXUserMX_InPanic)(void) = NULL;
-#define MXUSER_NOISE_FLOOR_TRIALS 1000
+#define MXUSER_MAX_LOOP 5
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_IsLockingTreeAvailable
+ *
+ * Is the lock tracking tree available for reporting?
+ *
+ * Results:
+ * TRUE MXuser lock tree tracking is enabled
+ * FALSE MXUser lock tree tracking is disabled
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUser_IsLockingTreeAvailable(void)
+{
+ return mxUserCollectLockingTree;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_LockingTreeCollection
+ *
+ * Enable or disable locking tree data collection.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_LockingTreeCollection(Bool enabled) // IN:
+{
+ mxUserCollectLockingTree = vmx86_devel && vmx86_debug && enabled;
+}
/*
@@ -64,7 +113,7 @@ static Bool (*MXUserMX_InPanic)(void) = NULL;
MXRecLock *
MXUserInternalSingleton(Atomic_Ptr *storage) // IN:
{
- MXRecLock *lock = (MXRecLock *) Atomic_ReadPtr(storage);
+ MXRecLock *lock = Atomic_ReadPtr(storage);
if (UNLIKELY(lock == NULL)) {
MXRecLock *newLock = Util_SafeMalloc(sizeof *newLock);
@@ -190,6 +239,34 @@ MXUserGetSignature(MXUserObjectType objectType) // IN:
/*
+ *---------------------------------------------------------------------
+ *
+ * MXUser_SetInPanic --
+ *
+ * Notify the locking system that a panic is occurring.
+ *
+ * Results:
+ * Set the "in a panic" state in userland locks and, when possible,
+ * MX locks.
+ *
+ * Side effects:
+ * None
+ *
+ *---------------------------------------------------------------------
+ */
+
+void
+MXUser_SetInPanic(void)
+{
+ mxInPanic = TRUE;
+
+ if (MXUserMX_SetInPanic != NULL) {
+ MXUserMX_SetInPanic();
+ }
+}
+
+
+/*
*-----------------------------------------------------------------------------
*
* MXUserDumpAndPanic --
@@ -212,9 +289,19 @@ MXUserDumpAndPanic(MXUserHeader *header, // IN:
{
char *msg;
va_list ap;
+ static uint32 loopCounter = 0; // Is panic looping through there?
ASSERT((header != NULL) && (header->dumpFunc != NULL));
+ if (++loopCounter > MXUSER_MAX_LOOP) {
+ /*
+ * Panic is looping through MXUser to here - no progress is being made.
+ * Switch to panic mode in the hopes that this will allow some progress.
+ */
+
+ MXUser_SetInPanic();
+ }
+
(*header->dumpFunc)(header);
va_start(ap, fmt);
@@ -228,33 +315,9 @@ MXUserDumpAndPanic(MXUserHeader *header, // IN:
/*
*---------------------------------------------------------------------
*
- * MXUser_SetInPanic --
- * Notify the locking system that a panic is occurring.
- *
- * Results:
- * Set the "in a panic" state both in userland, and monitor, if applicable.
- *
- * Side effects:
- * None
- *
- *---------------------------------------------------------------------
- */
-
-void
-MXUser_SetInPanic(void)
-{
- mxInPanic = TRUE;
- if (MXUserMX_SetInPanic != NULL) {
- MXUserMX_SetInPanic();
- }
-}
-
-
-/*
- *---------------------------------------------------------------------
- *
* MXUser_InPanic --
- * Is the caller in the midst of a panic?
+ *
+ * Is the caller in the midst of a panic?
*
* Results:
* TRUE Yes
@@ -294,12 +357,13 @@ MXUser_InPanic(void)
void
MXUserInstallMxHooks(void (*theLockListFunc)(void),
MX_Rank (*theRankFunc)(void),
- void (*theLockFunc)(struct MX_MutexRec *lock),
- void (*theUnlockFunc)(struct MX_MutexRec *lock),
- Bool (*theTryLockFunc)(struct MX_MutexRec *lock),
- Bool (*theIsLockedFunc)(const struct MX_MutexRec *lock),
- void (*theSetInPanicFunc)(void),
- Bool (*theInPanicFunc)(void))
+ void (*theLockFunc)(struct MX_MutexRec *lock),
+ void (*theUnlockFunc)(struct MX_MutexRec *lock),
+ Bool (*theTryLockFunc)(struct MX_MutexRec *lock),
+ Bool (*theIsLockedFunc)(const struct MX_MutexRec *lock),
+ char *(*theNameFunc)(const struct MX_MutexRec *lock),
+ void (*theSetInPanicFunc)(void),
+ Bool (*theInPanicFunc)(void))
{
/*
* This function can be called more than once but the second and later
@@ -313,6 +377,7 @@ MXUserInstallMxHooks(void (*theLockListFunc)(void),
(MXUserMX_UnlockRec == NULL) &&
(MXUserMX_TryLockRec == NULL) &&
(MXUserMX_IsLockedByCurThreadRec == NULL) &&
+ (MXUserMX_NameRec == NULL) &&
(MXUserMX_SetInPanic == NULL) &&
(MXUserMX_InPanic == NULL)
) {
@@ -322,6 +387,7 @@ MXUserInstallMxHooks(void (*theLockListFunc)(void),
MXUserMX_UnlockRec = theUnlockFunc;
MXUserMX_TryLockRec = theTryLockFunc;
MXUserMX_IsLockedByCurThreadRec = theIsLockedFunc;
+ MXUserMX_NameRec = theNameFunc;
MXUserMX_SetInPanic = theSetInPanicFunc;
MXUserMX_InPanic = theInPanicFunc;
} else {
@@ -331,6 +397,7 @@ MXUserInstallMxHooks(void (*theLockListFunc)(void),
(MXUserMX_UnlockRec == theUnlockFunc) &&
(MXUserMX_TryLockRec == theTryLockFunc) &&
(MXUserMX_IsLockedByCurThreadRec == theIsLockedFunc) &&
+ (MXUserMX_NameRec == theNameFunc) &&
(MXUserMX_SetInPanic == theSetInPanicFunc) &&
(MXUserMX_InPanic == theInPanicFunc)
);
@@ -351,7 +418,6 @@ static MXUserPerThread *perThreadFreeList = NULL;
static Atomic_Ptr hashTableMem;
-
/*
*-----------------------------------------------------------------------------
*
@@ -437,8 +503,10 @@ MXUserFreePerThread(MXUserPerThread *perThread) // IN:
MXRecLockAcquire(perThreadLock,
NULL); // non-stats
+
perThread->next = perThreadFreeList;
perThreadFreeList = perThread;
+
MXRecLockRelease(perThreadLock);
}
@@ -500,6 +568,7 @@ MXUserGetPerThread(Bool mayAlloc) // IN: alloc perThread if not present?
return perThread;
}
+
/*
*-----------------------------------------------------------------------------
*
@@ -510,10 +579,10 @@ MXUserGetPerThread(Bool mayAlloc) // IN: alloc perThread if not present?
* if no locks have been taken.
*
* Results:
- * The list is printed
+ * None
*
* Side effects:
- * None
+ * The list is printed.
*
*-----------------------------------------------------------------------------
*/
@@ -719,8 +788,28 @@ MXUserAcquisitionTracking(MXUserHeader *header, // IN:
}
}
- /* Add lock instance to the calling threads perThread information */
+ /* Add a lock instance to the calling threads perThread information */
perThread->lockArray[perThread->locksHeld++] = header;
+
+ /*
+ * Maintain the lock tracking tree when approporiate.
+ */
+
+ if (vmx86_devel && vmx86_debug && mxUserCollectLockingTree) {
+ uint32 i;
+ MXUserLockTreeNode *node = NULL;
+
+ MXUserLockTreeAcquire();
+
+ for (i = 0; i < perThread->locksHeld; i++) {
+ header = perThread->lockArray[i];
+
+ node = MXUserLockTreeAdd(node, header->name,
+ header->bits.serialNumber, header->rank);
+ }
+
+ MXUserLockTreeRelease();
+ }
}
@@ -772,7 +861,11 @@ MXUserReleaseTracking(MXUserHeader *header) // IN: lock, via its header
lastEntry = perThread->locksHeld - 1;
if (i < lastEntry) {
- perThread->lockArray[i] = perThread->lockArray[lastEntry];
+ uint32 j;
+
+ for (j = i + 1; j < perThread->locksHeld; j++) {
+ perThread->lockArray[i++] = perThread->lockArray[j];
+ }
}
perThread->lockArray[lastEntry] = NULL; // tidy up memory
@@ -794,7 +887,7 @@ MXUserReleaseTracking(MXUserHeader *header) // IN: lock, via its header
* Unknown
*
* Side effects:
- * Always entertaining...
+ * None
*
*-----------------------------------------------------------------------------
*/
@@ -811,14 +904,14 @@ MXUser_TryAcquireFailureControl(Bool (*func)(const char *name)) // IN:
*
* MXUserValidateHeader --
*
- * Validate an MXUser object header
+ * Validate an MXUser object header.
*
* Results:
* Return All is well
* Panic All is NOT well
*
* Side effects:
- * Always entertaining...
+ * None
*
*-----------------------------------------------------------------------------
*/
@@ -829,14 +922,24 @@ MXUserValidateHeader(MXUserHeader *header, // IN:
{
uint32 expected = MXUserGetSignature(objectType);
+ if (header->bits.badHeader == 1) {
+ return; // No need to panic on a bad header repeatedly...
+ }
+
if (header->signature != expected) {
+ header->bits.badHeader = 1;
+
MXUserDumpAndPanic(header,
"%s: signature failure! expected 0x%X observed 0x%X\n",
__FUNCTION__, expected, header->signature);
+
}
- if (header->serialNumber == 0) {
- MXUserDumpAndPanic(header, "%s: Invalid serial number!", __FUNCTION__);
+ if (header->bits.serialNumber == 0) {
+ header->bits.badHeader = 1;
+
+ MXUserDumpAndPanic(header, "%s: Invalid serial number!\n",
+ __FUNCTION__);
}
}
#endif
diff --git a/open-vm-tools/lib/lock/ulBarrier.c b/open-vm-tools/lib/lock/ulBarrier.c
index c965fa64..2c440596 100644
--- a/open-vm-tools/lib/lock/ulBarrier.c
+++ b/open-vm-tools/lib/lock/ulBarrier.c
@@ -67,7 +67,7 @@ MXUserDumpBarrier(MXUserHeader *header) // IN:
Warning("\tsignature 0x%X\n", barrier->header.signature);
Warning("\tname %s\n", barrier->header.name);
Warning("\trank 0x%X\n", barrier->header.rank);
- Warning("\tserial number %u\n", barrier->header.serialNumber);
+ Warning("\tserial number %u\n", barrier->header.bits.serialNumber);
Warning("\tlock 0x%p\n", barrier->lock);
Warning("\tconfigured count %u\n", barrier->configCount);
@@ -118,7 +118,7 @@ MXUser_CreateBarrier(const char *userName, // IN: shall be known as
ASSERT(count);
- barrier = Util_SafeCalloc(1, sizeof(*barrier));
+ barrier = Util_SafeCalloc(1, sizeof *barrier);
if (userName == NULL) {
properName = Str_SafeAsprintf(NULL, "Barrier-%p", GetReturnAddress());
@@ -157,7 +157,7 @@ MXUser_CreateBarrier(const char *userName, // IN: shall be known as
barrier->header.signature = MXUserGetSignature(MXUSER_TYPE_BARRIER);
barrier->header.name = properName;
barrier->header.rank = rank;
- barrier->header.serialNumber = MXUserAllocSerialNumber();
+ barrier->header.bits.serialNumber = MXUserAllocSerialNumber();
barrier->header.dumpFunc = MXUserDumpBarrier;
barrier->header.statsFunc = NULL;
@@ -184,7 +184,7 @@ MXUser_CreateBarrier(const char *userName, // IN: shall be known as
*/
void
-MXUser_DestroyBarrier(MXUserBarrier *barrier) // IN:
+MXUser_DestroyBarrier(MXUserBarrier *barrier) // IN/OUT:
{
if (LIKELY(barrier != NULL)) {
MXUserValidateHeader(&barrier->header, MXUSER_TYPE_BARRIER);
@@ -222,7 +222,7 @@ MXUser_DestroyBarrier(MXUserBarrier *barrier) // IN:
* threads that have entered reaches the configured number upon which
* time all of the threads will return from this routine.
*
- * "Nobody comes out until everone goes in."
+ * "Nobody comes out until everyone goes in."
*
* Results:
* None
@@ -311,19 +311,18 @@ MXUser_CreateSingletonBarrier(Atomic_Ptr *barrierStorage, // IN/OUT:
ASSERT(barrierStorage);
- barrier = (MXUserBarrier *) Atomic_ReadPtr(barrierStorage);
+ barrier = Atomic_ReadPtr(barrierStorage);
if (UNLIKELY(barrier == NULL)) {
MXUserBarrier *newBarrier = MXUser_CreateBarrier(name, rank, count);
- barrier = (MXUserBarrier *) Atomic_ReadIfEqualWritePtr(barrierStorage,
- NULL,
- (void *) newBarrier);
+ barrier = Atomic_ReadIfEqualWritePtr(barrierStorage, NULL,
+ (void *) newBarrier);
if (barrier) {
MXUser_DestroyBarrier(newBarrier);
} else {
- barrier = (MXUserBarrier *) Atomic_ReadPtr(barrierStorage);
+ barrier = Atomic_ReadPtr(barrierStorage);
}
}
diff --git a/open-vm-tools/lib/lock/ulCondVar.c b/open-vm-tools/lib/lock/ulCondVar.c
index 8e1a05c0..b2954486 100644
--- a/open-vm-tools/lib/lock/ulCondVar.c
+++ b/open-vm-tools/lib/lock/ulCondVar.c
@@ -221,15 +221,15 @@ MXUserDestroyInternal(MXUserCondVar *condVar) // IN/OUT:
* As above
*
* Side effects:
- * It is possible to return from this routine without the condtion
+ * It is possible to return from this routine without the condition
* variable having been signalled (spurious wake up); code accordingly!
*
*-----------------------------------------------------------------------------
*/
static INLINE void
-MXUserWaitInternal(MXRecLock *lock, // IN:
- MXUserCondVar *condVar, // IN:
+MXUserWaitInternal(MXRecLock *lock, // IN/OUT:
+ MXUserCondVar *condVar, // IN/OUT:
uint32 msecWait) // IN:
{
int lockCount = MXRecLockCount(lock);
@@ -356,7 +356,7 @@ MXUserSignalInternal(MXUserCondVar *condVar) // IN/OUT:
*
* MXUserBroadcastInternal --
*
- * Perform the environmentally specific portion of broadasting on an
+ * Perform the environmentally specific portion of broadcasting on an
* MXUserCondVar.
*
* Results:
@@ -451,15 +451,15 @@ MXUserDestroyInternal(MXUserCondVar *condVar) // IN/OUT:
* As above
*
* Side effects:
- * It is possible to return from this routine without the condtion
+ * It is possible to return from this routine without the condition
* variable having been signalled (spurious wake up); code accordingly!
*
*-----------------------------------------------------------------------------
*/
static INLINE void
-MXUserWaitInternal(MXRecLock *lock, // IN:
- MXUserCondVar *condVar, // IN:
+MXUserWaitInternal(MXRecLock *lock, // IN/OUT:
+ MXUserCondVar *condVar, // IN/OUT:
uint32 msecWait) // IN:
{
int err;
@@ -542,7 +542,7 @@ MXUserSignalInternal(MXUserCondVar *condVar) // IN/OUT:
*
* MXUserBroadcaseInternal --
*
- * Perform the environmentally specific portion of broadasting on an
+ * Perform the environmentally specific portion of broadcasting on an
* MXUserCondVar.
*
* Results:
@@ -620,8 +620,8 @@ MXUserCreateCondVar(MXUserHeader *header, // IN:
void
MXUserWaitCondVar(MXUserHeader *header, // IN:
- MXRecLock *lock, // IN:
- MXUserCondVar *condVar, // IN:
+ MXRecLock *lock, // IN/OUT:
+ MXUserCondVar *condVar, // IN/OUT:
uint32 msecWait) // IN:
{
ASSERT(header);
@@ -663,7 +663,7 @@ MXUserWaitCondVar(MXUserHeader *header, // IN:
*/
void
-MXUser_SignalCondVar(MXUserCondVar *condVar) // IN:
+MXUser_SignalCondVar(MXUserCondVar *condVar) // IN/OUT:
{
int err;
@@ -697,7 +697,7 @@ MXUser_SignalCondVar(MXUserCondVar *condVar) // IN:
*/
void
-MXUser_BroadcastCondVar(MXUserCondVar *condVar) // IN:
+MXUser_BroadcastCondVar(MXUserCondVar *condVar) // IN/OUT:
{
int err;
@@ -732,7 +732,7 @@ MXUser_BroadcastCondVar(MXUserCondVar *condVar) // IN:
*/
void
-MXUser_DestroyCondVar(MXUserCondVar *condVar) // IN:
+MXUser_DestroyCondVar(MXUserCondVar *condVar) // IN/OUT:
{
if (condVar != NULL) {
ASSERT(condVar->signature == MXUserGetSignature(MXUSER_TYPE_CONDVAR));
diff --git a/open-vm-tools/lib/lock/ulExcl.c b/open-vm-tools/lib/lock/ulExcl.c
index c6707590..f6031feb 100644
--- a/open-vm-tools/lib/lock/ulExcl.c
+++ b/open-vm-tools/lib/lock/ulExcl.c
@@ -22,20 +22,6 @@
#include "userlock.h"
#include "hostinfo.h"
#include "ulInt.h"
-#include "vm_atomic.h"
-
-typedef struct
-{
- MXUserAcquisitionStats data;
- Atomic_Ptr histo;
-} MXUserAcquireStats;
-
-typedef struct
-{
- VmTimeType holdStart;
- MXUserBasicStats data;
- Atomic_Ptr histo;
-} MXUserHeldStats;
struct MXUserExclLock
{
@@ -99,16 +85,14 @@ MXUserStatsActionExcl(MXUserHeader *header) // IN:
MXUserKitchen(&acquireStats->data, &contentionRatio, &isHot, &doLog);
if (UNLIKELY(isHot)) {
- MXUserForceHisto(&acquireStats->histo,
- MXUSER_STAT_CLASS_ACQUISITION,
- MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
- MXUSER_DEFAULT_HISTO_DECADES);
+ MXUserForceAcquisitionHisto(&lock->acquireStatsMem,
+ MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
+ MXUSER_DEFAULT_HISTO_DECADES);
if (UNLIKELY(heldStats != NULL)) {
- MXUserForceHisto(&heldStats->histo,
- MXUSER_STAT_CLASS_HELD,
- MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
- MXUSER_DEFAULT_HISTO_DECADES);
+ MXUserForceHeldHisto(&lock->heldStatsMem,
+ MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
+ MXUSER_DEFAULT_HISTO_DECADES);
}
if (doLog) {
@@ -123,144 +107,170 @@ MXUserStatsActionExcl(MXUserHeader *header) // IN:
/*
*-----------------------------------------------------------------------------
*
- * MXUser_ControlExclLock --
+ * MXUser_EnableStatsExclLock
*
- * Perform the specified command on the specified lock.
+ * Enable basic stats on the specified lock.
*
* Results:
* TRUE succeeded
* FALSE failed
*
* Side effects:
- * Depends on the command, no?
+ * None
*
*-----------------------------------------------------------------------------
*/
Bool
-MXUser_ControlExclLock(MXUserExclLock *lock, // IN/OUT:
- uint32 command, // IN:
- ...) // IN:
+MXUser_EnableStatsExclLock(MXUserExclLock *lock, // IN/OUT:
+ Bool trackAcquisitionTime, // IN:
+ Bool trackHeldTime) // IN:
{
- Bool result;
-
ASSERT(lock);
MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL);
- switch (command) {
- case MXUSER_CONTROL_ACQUISITION_HISTO: {
- if (vmx86_stats) {
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
-
- if (acquireStats == NULL) {
- result = FALSE;
- } else {
- va_list a;
- uint32 decades;
- uint64 minValue;
+ if (vmx86_stats) {
+ MXUserEnableStats(trackAcquisitionTime ? &lock->acquireStatsMem : NULL,
+ trackHeldTime ? &lock->heldStatsMem : NULL);
+ }
- va_start(a, command);
- minValue = va_arg(a, uint64);
- decades = va_arg(a, uint32);
- va_end(a);
+ return vmx86_stats;
+}
- MXUserForceHisto(&acquireStats->histo,
- MXUSER_STAT_CLASS_ACQUISITION, minValue, decades);
- result = TRUE;
- }
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_DisableStatsExclLock --
+ *
+ * Disable basic stats on the specified lock.
+ *
+ * Results:
+ * TRUE succeeded
+ * FALSE failed
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
- } else {
- result = FALSE;
- }
+Bool
+MXUser_DisableStatsExclLock(MXUserExclLock *lock) // IN/OUT:
+{
+ ASSERT(lock);
+ MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL);
- break;
+ if (vmx86_stats) {
+ MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
}
- case MXUSER_CONTROL_HELD_HISTO: {
- if (vmx86_stats) {
- MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem);
+ return vmx86_stats;
+}
- if (heldStats == NULL) {
- result = FALSE;
- } else {
- va_list a;
- uint32 decades;
- uint32 minValue;
- va_start(a, command);
- minValue = va_arg(a, uint64);
- decades = va_arg(a, uint32);
- va_end(a);
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_SetContentionRatioFloorExclLock --
+ *
+ * Set the contention ratio floor for the specified lock.
+ *
+ * Results:
+ * TRUE succeeded
+ * FALSE failed
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
- MXUserForceHisto(&heldStats->histo, MXUSER_STAT_CLASS_HELD,
- minValue, decades);
+Bool
+MXUser_SetContentionRatioFloorExclLock(MXUserExclLock *lock, // IN/OUT:
+ double ratio) // IN:
+{
+ Bool result;
- result = TRUE;
- }
- } else {
- result = FALSE;
- }
+ ASSERT(lock);
+ MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL);
- break;
+ if (vmx86_stats) {
+ result = MXUserSetContentionRatioFloor(&lock->acquireStatsMem, ratio);
+ } else {
+ result = FALSE;
}
- case MXUSER_CONTROL_ENABLE_STATS: {
- if (vmx86_stats) {
- va_list a;
- Bool trackHeldTimes;
- MXUserHeldStats *heldStats;
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
-
- if (LIKELY(acquireStats == NULL)) {
- MXUserAcquireStats *before;
-
- acquireStats = Util_SafeCalloc(1, sizeof(*acquireStats));
- MXUserAcquisitionStatsSetUp(&acquireStats->data);
-
- before = Atomic_ReadIfEqualWritePtr(&lock->acquireStatsMem, NULL,
- (void *) acquireStats);
+ return result;
+}
- if (before) {
- free(acquireStats);
- }
- }
- va_start(a, command);
- trackHeldTimes = va_arg(a, int);
- va_end(a);
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_SetContentionCountFloorExclLock --
+ *
+ * Set the contention count floor for the specified lock.
+ *
+ * Results:
+ * TRUE succeeded
+ * FALSE failed
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
- heldStats = Atomic_ReadPtr(&lock->heldStatsMem);
+Bool
+MXUser_SetContentionCountFloorExclLock(MXUserExclLock *lock, // IN/OUT:
+ uint64 count) // IN:
+{
+ Bool result;
- if ((heldStats == NULL) && trackHeldTimes) {
- MXUserHeldStats *before;
+ ASSERT(lock);
+ MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL);
- heldStats = Util_SafeCalloc(1, sizeof(*heldStats));
- MXUserBasicStatsSetUp(&heldStats->data, MXUSER_STAT_CLASS_HELD);
+ if (vmx86_stats) {
+ result = MXUserSetContentionCountFloor(&lock->acquireStatsMem, count);
+ } else {
+ result = FALSE;
+ }
- before = Atomic_ReadIfEqualWritePtr(&lock->heldStatsMem, NULL,
- (void *) heldStats);
+ return result;
+}
- if (before) {
- free(heldStats);
- }
- }
- lock->header.statsFunc = MXUserStatsActionExcl;
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_SetContentionDurationFloorExclLock --
+ *
+ * Set the contention count floor for the specified lock.
+ *
+ * Results:
+ * TRUE succeeded
+ * FALSE failed
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
- result = TRUE;
- } else {
- result = FALSE;
- }
+Bool
+MXUser_SetContentionDurationFloorExclLock(MXUserExclLock *lock, // IN/OUT:
+ uint64 duration) // IN:
+{
+ Bool result;
- break;
- }
+ ASSERT(lock);
+ MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL);
- default:
+ if (vmx86_stats) {
+ result = MXUserSetContentionDurationFloor(&lock->acquireStatsMem,
+ duration);
+ } else {
result = FALSE;
}
@@ -294,7 +304,7 @@ MXUserDumpExclLock(MXUserHeader *header) // IN:
Warning("\tsignature 0x%X\n", lock->header.signature);
Warning("\tname %s\n", lock->header.name);
Warning("\trank 0x%X\n", lock->header.rank);
- Warning("\tserial number %u\n", lock->header.serialNumber);
+ Warning("\tserial number %u\n", lock->header.bits.serialNumber);
Warning("\tlock count %d\n", MXRecLockCount(&lock->recursiveLock));
@@ -306,7 +316,7 @@ MXUserDumpExclLock(MXUserHeader *header) // IN:
/*
*-----------------------------------------------------------------------------
*
- * MXUserCreateExclLock --
+ * MXUser_CreateExclLock --
*
* Create an exclusive lock.
*
@@ -320,10 +330,9 @@ MXUserDumpExclLock(MXUserHeader *header) // IN:
*-----------------------------------------------------------------------------
*/
-static MXUserExclLock *
-MXUserCreateExclLock(const char *userName, // IN:
- MX_Rank rank, // IN:
- Bool beSilent) // IN:
+MXUserExclLock *
+MXUser_CreateExclLock(const char *userName, // IN:
+ MX_Rank rank) // IN:
{
uint32 statsMode;
char *properName;
@@ -345,24 +354,25 @@ MXUserCreateExclLock(const char *userName, // IN:
lock->header.signature = MXUserGetSignature(MXUSER_TYPE_EXCL);
lock->header.name = properName;
lock->header.rank = rank;
- lock->header.serialNumber = MXUserAllocSerialNumber();
+ lock->header.bits.serialNumber = MXUserAllocSerialNumber();
lock->header.dumpFunc = MXUserDumpExclLock;
- statsMode = beSilent ? 0 : MXUserStatsMode();
+ statsMode = MXUserStatsMode();
- switch (statsMode) {
+ switch (MXUserStatsMode()) {
case 0:
+ MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
lock->header.statsFunc = NULL;
- Atomic_WritePtr(&lock->acquireStatsMem, NULL);
- Atomic_WritePtr(&lock->heldStatsMem, NULL);
break;
case 1:
- MXUser_ControlExclLock(lock, MXUSER_CONTROL_ENABLE_STATS, FALSE);
+ MXUserEnableStats(&lock->acquireStatsMem, NULL);
+ lock->header.statsFunc = MXUserStatsActionExcl;
break;
case 2:
- MXUser_ControlExclLock(lock, MXUSER_CONTROL_ENABLE_STATS, TRUE);
+ MXUserEnableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
+ lock->header.statsFunc = MXUserStatsActionExcl;
break;
default:
@@ -374,58 +384,6 @@ MXUserCreateExclLock(const char *userName, // IN:
return lock;
}
-/*
- *-----------------------------------------------------------------------------
- *
- * MXUser_CreateExclLock --
- *
- * Create an exclusive lock. The lock may log messages, including
- * statistics and contention information.
- *
- * Results:
- * NULL Creation failed
- * !NULL Creation succeeded
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-MXUserExclLock *
-MXUser_CreateExclLock(const char *userName, // IN:
- MX_Rank rank) // IN:
-{
- return MXUserCreateExclLock(userName, rank, FALSE);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * MXUser_CreateExclLockSilent --
- *
- * Create an exclusive lock specifying if the lock must always be silent -
- * never logging any messages. Silent locks will never produce any
- * statistics or contention information.
- *
- * Results:
- * NULL Creation failed
- * !NULL Creation succeeded
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-MXUserExclLock *
-MXUser_CreateExclLockSilent(const char *userName, // IN:
- MX_Rank rank) // IN:
-{
- return MXUserCreateExclLock(userName, rank, TRUE);
-}
-
/*
*-----------------------------------------------------------------------------
@@ -455,35 +413,15 @@ MXUser_DestroyExclLock(MXUserExclLock *lock) // IN:
__FUNCTION__);
}
- lock->header.signature = 0; // just in case...
-
MXRecLockDestroy(&lock->recursiveLock);
MXUserRemoveFromList(&lock->header);
if (vmx86_stats) {
- MXUserHeldStats *heldStats;
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
-
- if (LIKELY(acquireStats != NULL)) {
- MXUserAcquisitionStatsTearDown(&acquireStats->data);
- MXUserHistoTearDown(Atomic_ReadPtr(&acquireStats->histo));
-
- free(acquireStats);
- }
-
- heldStats = Atomic_ReadPtr(&lock->heldStatsMem);
-
- if (UNLIKELY(heldStats != NULL)) {
- MXUserBasicStatsTearDown(&heldStats->data);
- MXUserHistoTearDown(Atomic_ReadPtr(&heldStats->histo));
-
- free(heldStats);
- }
+ MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
}
+ lock->header.signature = 0; // just in case...
free(lock->header.name);
lock->header.name = NULL;
free(lock);
@@ -529,7 +467,8 @@ MXUser_AcquireExclLock(MXUserExclLock *lock) // IN/OUT:
MXUserHisto *histo;
MXUserAcquisitionSample(&acquireStats->data, TRUE,
- value > mxUserContentionDurationFloor, value);
+ value > acquireStats->data.contentionDurationFloor,
+ value);
histo = Atomic_ReadPtr(&acquireStats->histo);
diff --git a/open-vm-tools/lib/lock/ulInt.h b/open-vm-tools/lib/lock/ulInt.h
index 099766f2..ed4f8ef0 100644
--- a/open-vm-tools/lib/lock/ulInt.h
+++ b/open-vm-tools/lib/lock/ulInt.h
@@ -41,6 +41,7 @@ typedef pthread_t MXUserThreadID;
#endif
#include "vm_basic_types.h"
+#include "vm_atomic.h"
#include "vthreadBase.h"
#include "hostinfo.h"
@@ -66,8 +67,6 @@ typedef struct {
MXUserThreadID nativeThreadID; // Native thread ID
} MXRecLock;
-extern VmTimeType mxUserContentionDurationFloor;
-
/*
* Environment specific implementations of portable recursive locks.
@@ -302,13 +301,27 @@ static INLINE void
MXRecLockIncCount(MXRecLock *lock, // IN/OUT:
int count) // IN:
{
+ int newCount = (lock->referenceCount += count);
+
ASSERT(count >= 0);
- if (MXRecLockCount(lock) == 0) {
+ if (LIKELY(newCount == count)) {
MXRecLockSetOwner(lock);
}
+}
+
+
+static INLINE void
+MXRecLockDecCount(MXRecLock *lock, // IN/OUT:
+ int count) // IN:
+{
+ int newCount = (lock->referenceCount -= count);
- lock->referenceCount += count;
+ ASSERT(count >= 0);
+
+ if (LIKELY(newCount == 0)) {
+ MXRecLockSetNoOwner(lock);
+ }
}
@@ -318,7 +331,7 @@ MXRecLockAcquire(MXRecLock *lock, // IN/OUT:
{
int err;
- if ((MXRecLockCount(lock) > 0) && MXRecLockIsOwner(lock)) {
+ if (UNLIKELY(MXRecLockCount(lock) > 0) && MXRecLockIsOwner(lock)) {
MXRecLockIncCount(lock, 1);
if (duration != NULL) {
@@ -355,7 +368,7 @@ MXRecLockTryAcquire(MXRecLock *lock) // IN/OUT:
{
int err;
- if ((MXRecLockCount(lock) > 0) && MXRecLockIsOwner(lock)) {
+ if (UNLIKELY(MXRecLockCount(lock) > 0) && MXRecLockIsOwner(lock)) {
MXRecLockIncCount(lock, 1);
return TRUE; // Was acquired
@@ -363,7 +376,7 @@ MXRecLockTryAcquire(MXRecLock *lock) // IN/OUT:
err = MXRecLockTryAcquireInternal(lock);
- if (err == 0) {
+ if (LIKELY(err == 0)) {
MXRecLockIncCount(lock, 1);
return TRUE; // Was acquired
@@ -378,25 +391,11 @@ MXRecLockTryAcquire(MXRecLock *lock) // IN/OUT:
static INLINE void
-MXRecLockDecCount(MXRecLock *lock, // IN/OUT:
- int count) // IN:
-{
- ASSERT(count >= 0);
-
- lock->referenceCount -= count;
-
- if (MXRecLockCount(lock) == 0) {
- MXRecLockSetNoOwner(lock);
- }
-}
-
-
-static INLINE void
MXRecLockRelease(MXRecLock *lock) // IN/OUT:
{
MXRecLockDecCount(lock, 1);
- if (MXRecLockCount(lock) == 0) {
+ if (LIKELY(MXRecLockCount(lock) == 0)) {
int err = MXRecLockReleaseInternal(lock);
if (vmx86_debug && (err != 0)) {
@@ -447,7 +446,8 @@ typedef enum {
MXUSER_TYPE_EXCL = 4,
MXUSER_TYPE_SEMA = 5,
MXUSER_TYPE_CONDVAR = 6,
- MXUSER_TYPE_BARRIER = 7
+ MXUSER_TYPE_BARRIER = 7,
+ MXUSER_TYPE_EVENT = 8
} MXUserObjectType;
/*
@@ -458,7 +458,12 @@ typedef struct MXUserHeader {
uint32 signature;
char *name;
MX_Rank rank;
- uint32 serialNumber;
+
+ struct {
+ unsigned int serialNumber : 24;
+ unsigned int badHeader: 1;
+ } bits;
+
void (*dumpFunc)(struct MXUserHeader *);
void (*statsFunc)(struct MXUserHeader *);
ListItem item;
@@ -535,6 +540,9 @@ typedef struct {
} MXUserBasicStats;
typedef struct {
+ double contentionRatioFloor;
+ uint64 contentionCountFloor;
+ uint64 contentionDurationFloor;
uint64 numAttempts;
uint64 numSuccesses;
uint64 numSuccessesContended;
@@ -548,6 +556,19 @@ typedef struct {
MXUserBasicStats basicStats; // total held statistics
} MXUserReleaseStats;
+typedef struct
+{
+ MXUserAcquisitionStats data;
+ Atomic_Ptr histo;
+} MXUserAcquireStats;
+
+typedef struct
+{
+ VmTimeType holdStart;
+ MXUserBasicStats data;
+ Atomic_Ptr histo;
+} MXUserHeldStats;
+
uint32 MXUserAllocSerialNumber(void);
void MXUserAddToList(MXUserHeader *header);
@@ -600,14 +621,36 @@ void MXUserKitchen(MXUserAcquisitionStats *stats,
Bool *isHot,
Bool *doLog);
-void MXUserForceHisto(Atomic_Ptr *histoPtr,
- char *typeName,
- uint64 minValue,
- uint32 decades);
+#define MXUSER_DEFAULT_HISTO_MIN_VALUE_NS 1000 // 1 usec
+#define MXUSER_DEFAULT_HISTO_DECADES 7 // 1 usec to 10 seconds
+
+Bool MXUserForceAcquisitionHisto(Atomic_Ptr *mem,
+ uint64 minValue,
+ uint32 decades);
+
+Bool MXUserForceHeldHisto(Atomic_Ptr *mem,
+ uint64 minValue,
+ uint32 decades);
+
+Bool MXUserSetContentionRatioFloor(Atomic_Ptr *mem,
+ double ratio);
+
+Bool MXUserSetContentionCountFloor(Atomic_Ptr *mem,
+ uint64 count);
+
+Bool MXUserSetContentionDurationFloor(Atomic_Ptr *mem,
+ uint64 count);
+
+void MXUserEnableStats(Atomic_Ptr *acquisitionMem,
+ Atomic_Ptr *heldMem);
+
+void MXUserDisableStats(Atomic_Ptr *acquisitionMem,
+ Atomic_Ptr *heldMem);
-extern void (*MXUserMX_LockRec)(struct MX_MutexRec *lock);
-extern void (*MXUserMX_UnlockRec)(struct MX_MutexRec *lock);
-extern Bool (*MXUserMX_TryLockRec)(struct MX_MutexRec *lock);
-extern Bool (*MXUserMX_IsLockedByCurThreadRec)(const struct MX_MutexRec *lock);
+extern void (*MXUserMX_LockRec)(struct MX_MutexRec *lock);
+extern void (*MXUserMX_UnlockRec)(struct MX_MutexRec *lock);
+extern Bool (*MXUserMX_TryLockRec)(struct MX_MutexRec *lock);
+extern Bool (*MXUserMX_IsLockedByCurThreadRec)(const struct MX_MutexRec *lock);
+extern char *(*MXUserMX_NameRec)(const struct MX_MutexRec *lock);
#endif
diff --git a/open-vm-tools/lib/lock/ulIntShared.h b/open-vm-tools/lib/lock/ulIntShared.h
index 9bc57d54..3a09cf01 100644
--- a/open-vm-tools/lib/lock/ulIntShared.h
+++ b/open-vm-tools/lib/lock/ulIntShared.h
@@ -38,7 +38,18 @@ extern void MXUserInstallMxHooks(void (*theLockListFunc)(void),
void (*theUnlockFunc)(struct MX_MutexRec *lock),
Bool (*theTryLockFunc)(struct MX_MutexRec *lock),
Bool (*theIsLockedFunc)(const struct MX_MutexRec *lock),
+ char *(*theNameFunc)(const struct MX_MutexRec *lock),
void (*theSetInPanicFunc)(void),
Bool (*theInPanicFunc)(void));
+typedef struct MXUserLockTreeNode MXUserLockTreeNode;
+
+void MXUserLockTreeAcquire(void);
+void MXUserLockTreeRelease(void);
+
+MXUserLockTreeNode *MXUserLockTreeAdd(MXUserLockTreeNode *searchNode,
+ const char *name,
+ uint32 serialNumber,
+ MX_Rank rank);
+
#endif
diff --git a/open-vm-tools/lib/lock/ulRW.c b/open-vm-tools/lib/lock/ulRW.c
index 57efce46..1f9d60d8 100644
--- a/open-vm-tools/lib/lock/ulRW.c
+++ b/open-vm-tools/lib/lock/ulRW.c
@@ -29,13 +29,6 @@
#include "hostinfo.h"
#include "ulInt.h"
-static void
-MXUserFreeHashEntry(void *data) // IN:
-{
- free(data);
-}
-
-
/*
* Environment specific implementations of portable read-write locks.
*
@@ -245,18 +238,6 @@ typedef struct {
VmTimeType holdStart;
} HolderContext;
-typedef struct
-{
- MXUserAcquisitionStats data;
- Atomic_Ptr histo;
-} MXUserAcquireStats;
-
-typedef struct
-{
- MXUserBasicStats data;
- Atomic_Ptr histo;
-} MXUserHeldStats;
-
struct MXUserRWLock
{
MXUserHeader header;
@@ -326,16 +307,14 @@ MXUserStatsActionRW(MXUserHeader *header) // IN:
MXUserKitchen(&acquireStats->data, &contentionRatio, &isHot, &doLog);
if (isHot) {
- MXUserForceHisto(&acquireStats->histo,
- MXUSER_STAT_CLASS_ACQUISITION,
- MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
- MXUSER_DEFAULT_HISTO_DECADES);
+ MXUserForceAcquisitionHisto(&lock->acquireStatsMem,
+ MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
+ MXUSER_DEFAULT_HISTO_DECADES);
if (heldStats) {
- MXUserForceHisto(&heldStats->histo,
- MXUSER_STAT_CLASS_HELD,
- MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
- MXUSER_DEFAULT_HISTO_DECADES);
+ MXUserForceHeldHisto(&lock->heldStatsMem,
+ MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
+ MXUSER_DEFAULT_HISTO_DECADES);
}
if (doLog) {
@@ -350,153 +329,6 @@ MXUserStatsActionRW(MXUserHeader *header) // IN:
/*
*-----------------------------------------------------------------------------
*
- * MXUser_ControlRWLock --
- *
- * Perform the specified command on the specified lock.
- *
- * Results:
- * TRUE succeeded
- * FALSE failed
- *
- * Side effects:
- * Depends on the command, no?
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-MXUser_ControlRWLock(MXUserRWLock *lock, // IN/OUT:
- uint32 command, // IN:
- ...) // IN:
-{
- Bool result;
-
- ASSERT(lock);
- MXUserValidateHeader(&lock->header, MXUSER_TYPE_RW);
-
- switch (command) {
- case MXUSER_CONTROL_ACQUISITION_HISTO: {
- if (vmx86_stats) {
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
-
- if (acquireStats == NULL) {
- result = FALSE;
- } else {
- va_list a;
- uint32 decades;
- uint64 minValue;
-
- va_start(a, command);
- minValue = va_arg(a, uint64);
- decades = va_arg(a, uint32);
- va_end(a);
-
- MXUserForceHisto(&acquireStats->histo,
- MXUSER_STAT_CLASS_ACQUISITION, minValue, decades);
-
- result = TRUE;
- }
- } else {
- result = FALSE;
- }
-
- break;
- }
-
- case MXUSER_CONTROL_HELD_HISTO: {
- if (vmx86_stats) {
- MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem);
-
- if (heldStats == NULL) {
- result = FALSE;
- } else {
- va_list a;
- uint32 decades;
- uint32 minValue;
-
- va_start(a, command);
- minValue = va_arg(a, uint64);
- decades = va_arg(a, uint32);
- va_end(a);
-
- MXUserForceHisto(&heldStats->histo, MXUSER_STAT_CLASS_HELD,
- minValue, decades);
-
- result = TRUE;
- }
- } else {
- result = FALSE;
- }
-
- break;
- }
-
- case MXUSER_CONTROL_ENABLE_STATS: {
- if (vmx86_stats) {
- va_list a;
- Bool trackHeldTimes;
- MXUserHeldStats *heldStats;
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
-
- if (LIKELY(acquireStats == NULL)) {
- MXUserAcquireStats *before;
-
- acquireStats = Util_SafeCalloc(1, sizeof *acquireStats);
- MXUserAcquisitionStatsSetUp(&acquireStats->data);
-
- before = Atomic_ReadIfEqualWritePtr(&lock->acquireStatsMem, NULL,
- (void *) acquireStats);
-
- if (before) {
- free(acquireStats);
- }
- }
-
- va_start(a, command);
- trackHeldTimes = va_arg(a, int);
- va_end(a);
-
- heldStats = Atomic_ReadPtr(&lock->heldStatsMem);
-
- if ((heldStats == NULL) && trackHeldTimes) {
- MXUserHeldStats *before;
-
- heldStats = Util_SafeCalloc(1, sizeof *heldStats);
- MXUserBasicStatsSetUp(&heldStats->data, MXUSER_STAT_CLASS_HELD);
-
- before = Atomic_ReadIfEqualWritePtr(&lock->heldStatsMem, NULL,
- (void *) heldStats);
-
- if (before) {
- free(heldStats);
- }
- }
-
- lock->header.statsFunc = MXUserStatsActionRW;
-
- result = TRUE;
- } else {
- result = FALSE;
- }
-
- break;
- }
-
- default:
- result = FALSE;
- }
-
- return result;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
* MXUserDumpRWLock --
*
* Dump an read-write lock.
@@ -520,7 +352,7 @@ MXUserDumpRWLock(MXUserHeader *header) // IN:
Warning("\tsignature 0x%X\n", lock->header.signature);
Warning("\tname %s\n", lock->header.name);
Warning("\trank 0x%X\n", lock->header.rank);
- Warning("\tserial number %u\n", lock->header.serialNumber);
+ Warning("\tserial number %u\n", lock->header.bits.serialNumber);
if (LIKELY(lock->useNative)) {
Warning("\taddress of native lock 0x%p\n", &lock->nativeLock);
@@ -552,6 +384,12 @@ MXUserDumpRWLock(MXUserHeader *header) // IN:
*-----------------------------------------------------------------------------
*/
+static void
+MXUserFreeHashEntry(void *data) // IN:
+{
+ free(data);
+}
+
MXUserRWLock *
MXUser_CreateRWLock(const char *userName, // IN:
MX_Rank rank) // IN:
@@ -575,7 +413,7 @@ MXUser_CreateRWLock(const char *userName, // IN:
lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW);
lock->header.name = properName;
lock->header.rank = rank;
- lock->header.serialNumber = MXUserAllocSerialNumber();
+ lock->header.bits.serialNumber = MXUserAllocSerialNumber();
lock->header.dumpFunc = MXUserDumpRWLock;
/*
@@ -597,19 +435,20 @@ MXUser_CreateRWLock(const char *userName, // IN:
statsMode = MXUserStatsMode();
- switch (statsMode) {
+ switch (MXUserStatsMode()) {
case 0:
+ MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
lock->header.statsFunc = NULL;
- Atomic_WritePtr(&lock->acquireStatsMem, NULL);
- Atomic_WritePtr(&lock->heldStatsMem, NULL);
break;
case 1:
- MXUser_ControlRWLock(lock, MXUSER_CONTROL_ENABLE_STATS, FALSE);
+ MXUserEnableStats(&lock->acquireStatsMem, NULL);
+ lock->header.statsFunc = MXUserStatsActionRW;
break;
case 2:
- MXUser_ControlRWLock(lock, MXUSER_CONTROL_ENABLE_STATS, TRUE);
+ MXUserEnableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
+ lock->header.statsFunc = MXUserStatsActionRW;
break;
default:
@@ -668,36 +507,17 @@ MXUser_DestroyRWLock(MXUserRWLock *lock) // IN:
}
}
- lock->header.signature = 0; // just in case...
-
MXRecLockDestroy(&lock->recursiveLock);
MXUserRemoveFromList(&lock->header);
if (vmx86_stats) {
- MXUserHeldStats *heldStats;
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
-
- if (LIKELY(acquireStats != NULL)) {
- MXUserAcquisitionStatsTearDown(&acquireStats->data);
- MXUserHistoTearDown(Atomic_ReadPtr(&acquireStats->histo));
-
- free(acquireStats);
- }
-
- heldStats = Atomic_ReadPtr(&lock->heldStatsMem);
-
- if (UNLIKELY(heldStats != NULL)) {
- MXUserBasicStatsTearDown(&heldStats->data);
- MXUserHistoTearDown(Atomic_ReadPtr(&heldStats->histo));
-
- free(heldStats);
- }
+ MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
}
HashTable_FreeUnsafe(lock->holderTable);
+
+ lock->header.signature = 0; // just in case...
free(lock->header.name);
lock->header.name = NULL;
free(lock);
@@ -827,7 +647,8 @@ MXUserAcquisition(MXUserRWLock *lock, // IN/OUT:
}
MXUserAcquisitionSample(&acquireStats->data, TRUE,
- value > mxUserContentionDurationFloor, value);
+ value > acquireStats->data.contentionDurationFloor,
+ value);
histo = Atomic_ReadPtr(&acquireStats->histo);
diff --git a/open-vm-tools/lib/lock/ulRec.c b/open-vm-tools/lib/lock/ulRec.c
index 8b7142c3..7067a057 100644
--- a/open-vm-tools/lib/lock/ulRec.c
+++ b/open-vm-tools/lib/lock/ulRec.c
@@ -22,20 +22,6 @@
#include "userlock.h"
#include "hostinfo.h"
#include "ulInt.h"
-#include "vm_atomic.h"
-
-typedef struct
-{
- MXUserAcquisitionStats data;
- Atomic_Ptr histo;
-} MXUserAcquireStats;
-
-typedef struct
-{
- VmTimeType holdStart;
- MXUserBasicStats data;
- Atomic_Ptr histo;
-} MXUserHeldStats;
struct MXUserRecLock
{
@@ -113,16 +99,14 @@ MXUserStatsActionRec(MXUserHeader *header) // IN:
MXUserKitchen(&acquireStats->data, &contentionRatio, &isHot, &doLog);
if (UNLIKELY(isHot)) {
- MXUserForceHisto(&acquireStats->histo,
- MXUSER_STAT_CLASS_ACQUISITION,
- MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
- MXUSER_DEFAULT_HISTO_DECADES);
+ MXUserForceAcquisitionHisto(&lock->acquireStatsMem,
+ MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
+ MXUSER_DEFAULT_HISTO_DECADES);
if (UNLIKELY(heldStats != NULL)) {
- MXUserForceHisto(&heldStats->histo,
- MXUSER_STAT_CLASS_HELD,
- MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
- MXUSER_DEFAULT_HISTO_DECADES);
+ MXUserForceHeldHisto(&lock->heldStatsMem,
+ MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
+ MXUSER_DEFAULT_HISTO_DECADES);
}
if (doLog) {
@@ -137,152 +121,173 @@ MXUserStatsActionRec(MXUserHeader *header) // IN:
/*
*-----------------------------------------------------------------------------
*
- * MXUser_ControlRecLock --
+ * MXUser_EnableStatsRecLock
*
- * Perform the specified command on the specified lock.
+ * Enable basic stats on the specified lock.
*
* Results:
* TRUE succeeded
* FALSE failed
*
* Side effects:
- * Depends on the command, no?
+ * None
*
*-----------------------------------------------------------------------------
*/
Bool
-MXUser_ControlRecLock(MXUserRecLock *lock, // IN/OUT:
- uint32 command, // IN:
- ...) // IN:
+MXUser_EnableStatsRecLock(MXUserRecLock *lock, // IN/OUT:
+ Bool trackAcquisitionTime, // IN:
+ Bool trackHeldTime) // IN:
{
- Bool result;
-
ASSERT(lock);
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
- Atomic_Inc(&lock->refCount);
-
- switch (command) {
- case MXUSER_CONTROL_ACQUISITION_HISTO: {
- if (vmx86_stats) {
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
+ if (vmx86_stats) {
+ MXUserEnableStats(trackAcquisitionTime ? &lock->acquireStatsMem : NULL,
+ trackHeldTime ? &lock->heldStatsMem : NULL);
+ }
- if ((acquireStats != NULL) && (lock->vmmLock == NULL)) {
- va_list a;
- uint32 decades;
- uint64 minValue;
+ return vmx86_stats;
+}
- va_start(a, command);
- minValue = va_arg(a, uint64);
- decades = va_arg(a, uint32);
- va_end(a);
- MXUserForceHisto(&acquireStats->histo,
- MXUSER_STAT_CLASS_ACQUISITION, minValue, decades);
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_DisableStatsRecLock --
+ *
+ * Disable basic stats on the specified lock.
+ *
+ * Results:
+ * TRUE succeeded
+ * FALSE failed
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
- result = TRUE;
- } else {
- result = FALSE;
- }
- } else {
- result = FALSE;
- }
+Bool
+MXUser_DisableStatsRecLock(MXUserRecLock *lock) // IN/OUT:
+{
+ ASSERT(lock);
+ MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
- break;
+ if (vmx86_stats) {
+ MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
}
- case MXUSER_CONTROL_HELD_HISTO: {
- if (vmx86_stats) {
- MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem);
+ return vmx86_stats;
+}
- if ((heldStats != NULL) && (lock->vmmLock == NULL)) {
- va_list a;
- uint32 decades;
- uint32 minValue;
- va_start(a, command);
- minValue = va_arg(a, uint64);
- decades = va_arg(a, uint32);
- va_end(a);
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_SetContentionRatioFloorRecLock --
+ *
+ * Set the contention ratio floor for the specified lock.
+ *
+ * Results:
+ * TRUE succeeded
+ * FALSE failed
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
- MXUserForceHisto(&heldStats->histo, MXUSER_STAT_CLASS_HELD,
- minValue, decades);
+Bool
+MXUser_SetContentionRatioFloorRecLock(MXUserRecLock *lock, // IN/OUT:
+ double ratio) // IN:
+{
+ Bool result;
- result = TRUE;
- } else {
- result = FALSE;
- }
- } else {
- result = FALSE;
- }
+ ASSERT(lock);
+ MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
- break;
+ if (vmx86_stats) {
+ result = MXUserSetContentionRatioFloor(&lock->acquireStatsMem, ratio);
+ } else {
+ result = FALSE;
}
- case MXUSER_CONTROL_ENABLE_STATS: {
- if (vmx86_stats) {
- va_list a;
- Bool trackHeldTimes;
- MXUserHeldStats *heldStats;
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
-
- if (LIKELY(acquireStats == NULL)) {
- MXUserAcquireStats *before;
-
- acquireStats = Util_SafeCalloc(1, sizeof *acquireStats);
- MXUserAcquisitionStatsSetUp(&acquireStats->data);
-
- before = Atomic_ReadIfEqualWritePtr(&lock->acquireStatsMem, NULL,
- (void *) acquireStats);
+ return result;
+}
- if (before) {
- free(acquireStats);
- }
- }
- va_start(a, command);
- trackHeldTimes = va_arg(a, int);
- va_end(a);
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_SetContentionCountFloorRecLock --
+ *
+ * Set the contention count floor for the specified lock.
+ *
+ * Results:
+ * TRUE succeeded
+ * FALSE failed
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
- heldStats = Atomic_ReadPtr(&lock->heldStatsMem);
+Bool
+MXUser_SetContentionCountFloorRecLock(MXUserRecLock *lock, // IN/OUT:
+ uint64 count) // IN:
+{
+ Bool result;
- if ((heldStats == NULL) && trackHeldTimes) {
- MXUserHeldStats *before;
+ ASSERT(lock);
+ MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
- heldStats = Util_SafeCalloc(1, sizeof *heldStats);
- MXUserBasicStatsSetUp(&heldStats->data, MXUSER_STAT_CLASS_HELD);
+ if (vmx86_stats) {
+ result = MXUserSetContentionCountFloor(&lock->acquireStatsMem, count);
+ } else {
+ result = FALSE;
+ }
- before = Atomic_ReadIfEqualWritePtr(&lock->heldStatsMem, NULL,
- (void *) heldStats);
+ return result;
+}
- if (before) {
- free(heldStats);
- }
- }
- lock->header.statsFunc = MXUserStatsActionRec;
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_SetContentionDurationFloorRecLock --
+ *
+ * Set the contention count floor for the specified lock.
+ *
+ * Results:
+ * TRUE succeeded
+ * FALSE failed
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
- result = TRUE;
- } else {
- result = FALSE;
- }
+Bool
+MXUser_SetContentionDurationFloorRecLock(MXUserRecLock *lock, // IN/OUT:
+ uint64 duration) // IN:
+{
+ Bool result;
- break;
- }
+ ASSERT(lock);
+ MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
- default:
+ if (vmx86_stats) {
+ result = MXUserSetContentionDurationFloor(&lock->acquireStatsMem,
+ duration);
+ } else {
result = FALSE;
}
- if (Atomic_ReadDec32(&lock->refCount) == 1) {
- Panic("%s: Zero reference count upon exit\n", __FUNCTION__);
- }
-
return result;
}
@@ -313,7 +318,7 @@ MXUserDumpRecLock(MXUserHeader *header) // IN:
Warning("\tsignature 0x%X\n", lock->header.signature);
Warning("\tname %s\n", lock->header.name);
Warning("\trank 0x%X\n", lock->header.rank);
- Warning("\tserial number %u\n", lock->header.serialNumber);
+ Warning("\tserial number %u\n", lock->header.bits.serialNumber);
Warning("\treference count %u\n", Atomic_Read(&lock->refCount));
if (lock->vmmLock == NULL) {
@@ -330,7 +335,7 @@ MXUserDumpRecLock(MXUserHeader *header) // IN:
/*
*-----------------------------------------------------------------------------
*
- * MXUserCreateRecLock --
+ * MXUser_CreateRecLock --
*
* Create a recursive lock specifying if the lock must always be
* silent.
@@ -347,10 +352,9 @@ MXUserDumpRecLock(MXUserHeader *header) // IN:
*-----------------------------------------------------------------------------
*/
-static MXUserRecLock *
-MXUserCreateRecLock(const char *userName, // IN:
- MX_Rank rank, // IN:
- Bool beSilent) // IN:
+MXUserRecLock *
+MXUser_CreateRecLock(const char *userName, // IN:
+ MX_Rank rank) // IN:
{
uint32 statsMode;
char *properName;
@@ -375,24 +379,25 @@ MXUserCreateRecLock(const char *userName, // IN:
lock->header.signature = MXUserGetSignature(MXUSER_TYPE_REC);
lock->header.name = properName;
lock->header.rank = rank;
- lock->header.serialNumber = MXUserAllocSerialNumber();
+ lock->header.bits.serialNumber = MXUserAllocSerialNumber();
lock->header.dumpFunc = MXUserDumpRecLock;
- statsMode = beSilent ? 0 : MXUserStatsMode();
+ statsMode = MXUserStatsMode();
switch (statsMode) {
case 0:
+ MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
lock->header.statsFunc = NULL;
- Atomic_WritePtr(&lock->acquireStatsMem, NULL);
- Atomic_WritePtr(&lock->heldStatsMem, NULL);
break;
case 1:
- MXUser_ControlRecLock(lock, MXUSER_CONTROL_ENABLE_STATS, FALSE);
+ MXUserEnableStats(&lock->acquireStatsMem, NULL);
+ lock->header.statsFunc = MXUserStatsActionRec;
break;
case 2:
- MXUser_ControlRecLock(lock, MXUSER_CONTROL_ENABLE_STATS, TRUE);
+ MXUserEnableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
+ lock->header.statsFunc = MXUserStatsActionRec;
break;
default:
@@ -408,62 +413,6 @@ MXUserCreateRecLock(const char *userName, // IN:
/*
*-----------------------------------------------------------------------------
*
- * MXUser_CreateRecLockSilent --
- *
- * Create a recursive lock specifying if the lock must always be
- * silent - never logging any messages. Silent locks will never
- * produce any statistics or contention information.
- *
- * Only the owner (thread) of a recursive lock may recurse on it.
- *
- * Results:
- * NULL Creation failed
- * !NULL Creation succeeded
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-MXUserRecLock *
-MXUser_CreateRecLockSilent(const char *userName, // IN:
- MX_Rank rank) // IN:
-{
- return MXUserCreateRecLock(userName, rank, TRUE);
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * MXUser_CreateRecLock --
- *
- * Create a recursive lock. The lock may log messages, including
- * statistics and contention information.
- *
- * Only the owner (thread) of a recursive lock may recurse on it.
- *
- * Results:
- * NULL Creation failed
- * !NULL Creation succeeded
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-MXUserRecLock *
-MXUser_CreateRecLock(const char *userName, // IN:
- MX_Rank rank) // IN:
-{
- return MXUserCreateRecLock(userName, rank, FALSE);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
* MXUserCondDestroyRecLock --
*
* Destroy a recursive lock -- but only if its reference count is zero.
@@ -487,6 +436,7 @@ MXUserCondDestroyRecLock(MXUserRecLock *lock) // IN:
{
ASSERT(lock);
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
+ ASSERT(Atomic_Read(&lock->refCount) > 0);
if (Atomic_ReadDec32(&lock->refCount) == 1) {
if (lock->vmmLock == NULL) {
@@ -501,26 +451,7 @@ MXUserCondDestroyRecLock(MXUserRecLock *lock) // IN:
MXUserRemoveFromList(&lock->header);
if (vmx86_stats) {
- MXUserHeldStats *heldStats;
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
-
- if (acquireStats) {
- MXUserAcquisitionStatsTearDown(&acquireStats->data);
- MXUserHistoTearDown(Atomic_ReadPtr(&acquireStats->histo));
-
- free(acquireStats);
- }
-
- heldStats = Atomic_ReadPtr(&lock->heldStatsMem);
-
- if (UNLIKELY(heldStats != NULL)) {
- MXUserBasicStatsTearDown(&heldStats->data);
- MXUserHistoTearDown(Atomic_ReadPtr(&heldStats->histo));
-
- free(heldStats);
- }
+ MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
}
}
@@ -543,7 +474,7 @@ MXUser_DestroyRecLock(MXUserRecLock *lock) // IN:
/*
*-----------------------------------------------------------------------------
*
- * MXUserAcquireRecLock --
+ * MXUser_AcquireRecLock --
*
* An acquisition is made (lock is taken) on the specified recursive lock.
*
@@ -563,10 +494,9 @@ MXUser_AcquireRecLock(MXUserRecLock *lock) // IN/OUT:
{
ASSERT(lock);
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
+ ASSERT(Atomic_Read(&lock->refCount) > 0);
- Atomic_Inc(&lock->refCount);
-
- if (lock->vmmLock) {
+ if (UNLIKELY(lock->vmmLock != NULL)) {
ASSERT(MXUserMX_LockRec);
(*MXUserMX_LockRec)(lock->vmmLock);
} else {
@@ -588,7 +518,7 @@ MXUser_AcquireRecLock(MXUserRecLock *lock) // IN/OUT:
MXUserHisto *histo;
MXUserAcquisitionSample(&acquireStats->data, TRUE,
- value > mxUserContentionDurationFloor,
+ value > acquireStats->data.contentionDurationFloor,
value);
histo = Atomic_ReadPtr(&acquireStats->histo);
@@ -609,10 +539,6 @@ MXUser_AcquireRecLock(MXUserRecLock *lock) // IN/OUT:
NULL); // non-stats
}
}
-
- if (Atomic_ReadDec32(&lock->refCount) == 1) {
- Panic("%s: Zero reference count upon exit\n", __FUNCTION__);
- }
}
@@ -637,10 +563,9 @@ MXUser_ReleaseRecLock(MXUserRecLock *lock) // IN/OUT:
{
ASSERT(lock);
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
+ ASSERT(Atomic_Read(&lock->refCount) > 0);
- Atomic_Inc(&lock->refCount);
-
- if (lock->vmmLock) {
+ if (UNLIKELY(lock->vmmLock != NULL)) {
ASSERT(MXUserMX_UnlockRec);
(*MXUserMX_UnlockRec)(lock->vmmLock);
} else {
@@ -687,14 +612,6 @@ MXUser_ReleaseRecLock(MXUserRecLock *lock) // IN/OUT:
MXRecLockRelease(&lock->recursiveLock);
}
-
- /*
- * Don't screw up the reference count! When this is the last reference
- * the lock will self destruct on a release if it is the last "hold"
- * of the lock.
- */
-
- MXUserCondDestroyRecLock(lock);
}
@@ -728,10 +645,9 @@ MXUser_TryAcquireRecLock(MXUserRecLock *lock) // IN/OUT:
ASSERT(lock);
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
+ ASSERT(Atomic_Read(&lock->refCount) > 0);
- Atomic_Inc(&lock->refCount);
-
- if (lock->vmmLock) {
+ if (UNLIKELY(lock->vmmLock != NULL)) {
ASSERT(MXUserMX_TryLockRec);
success = (*MXUserMX_TryLockRec)(lock->vmmLock);
} else {
@@ -759,11 +675,6 @@ MXUser_TryAcquireRecLock(MXUserRecLock *lock) // IN/OUT:
}
bail:
-
- if (Atomic_ReadDec32(&lock->refCount) == 1) {
- Panic("%s: Zero reference count upon exit\n", __FUNCTION__);
- }
-
return success;
}
@@ -792,20 +703,15 @@ MXUser_IsCurThreadHoldingRecLock(MXUserRecLock *lock) // IN:
ASSERT(lock);
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
+ ASSERT(Atomic_Read(&lock->refCount) > 0);
- Atomic_Inc(&lock->refCount);
-
- if (lock->vmmLock) {
+ if (UNLIKELY(lock->vmmLock != NULL)) {
ASSERT(MXUserMX_IsLockedByCurThreadRec);
result = (*MXUserMX_IsLockedByCurThreadRec)(lock->vmmLock);
} else {
result = MXRecLockIsOwner(&lock->recursiveLock);
}
- if (Atomic_ReadDec32(&lock->refCount) == 1) {
- Panic("%s: Zero reference count upon exit\n", __FUNCTION__);
- }
-
return result;
}
@@ -882,14 +788,8 @@ MXUser_CreateCondVarRecLock(MXUserRecLock *lock)
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
ASSERT(lock->vmmLock == NULL); // only unbound locks
- Atomic_Inc(&lock->refCount);
-
condVar = MXUserCreateCondVar(&lock->header, &lock->recursiveLock);
- if (Atomic_ReadDec32(&lock->refCount) == 1) {
- Panic("%s: Zero reference count upon exit\n", __FUNCTION__);
- }
-
return condVar;
}
@@ -921,14 +821,8 @@ MXUser_WaitCondVarRecLock(MXUserRecLock *lock, // IN:
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
ASSERT(lock->vmmLock == NULL); // only unbound locks
- Atomic_Inc(&lock->refCount);
-
MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar,
MXUSER_WAIT_INFINITE);
-
- if (Atomic_ReadDec32(&lock->refCount) == 1) {
- Panic("%s: Zero reference count upon exit\n", __FUNCTION__);
- }
}
@@ -960,13 +854,7 @@ MXUser_TimedWaitCondVarRecLock(MXUserRecLock *lock, // IN:
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
ASSERT(lock->vmmLock == NULL); // only unbound locks
- Atomic_Inc(&lock->refCount);
-
MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar, msecWait);
-
- if (Atomic_ReadDec32(&lock->refCount) == 1) {
- Panic("%s: Zero reference count upon exit\n", __FUNCTION__);
- }
}
@@ -992,13 +880,7 @@ MXUser_DumpRecLock(MXUserRecLock *lock) // IN:
ASSERT(lock);
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
- Atomic_Inc(&lock->refCount);
-
MXUserDumpRecLock(&lock->header);
-
- if (Atomic_ReadDec32(&lock->refCount) == 1) {
- Panic("%s: Zero reference count upon exit\n", __FUNCTION__);
- }
}
@@ -1076,6 +958,7 @@ MXUserRecLock *
MXUser_BindMXMutexRec(struct MX_MutexRec *mutex, // IN:
MX_Rank rank) // IN:
{
+ char *name;
MXUserRecLock *lock;
ASSERT(mutex);
@@ -1088,7 +971,8 @@ MXUser_BindMXMutexRec(struct MX_MutexRec *mutex, // IN:
if ((MXUserMX_LockRec == NULL) ||
(MXUserMX_UnlockRec == NULL) ||
(MXUserMX_TryLockRec == NULL) ||
- (MXUserMX_IsLockedByCurThreadRec == NULL)) {
+ (MXUserMX_IsLockedByCurThreadRec == NULL) ||
+ (MXUserMX_NameRec == NULL)) {
return NULL;
}
@@ -1101,9 +985,17 @@ MXUser_BindMXMutexRec(struct MX_MutexRec *mutex, // IN:
lock = Util_SafeCalloc(1, sizeof *lock);
lock->header.signature = MXUserGetSignature(MXUSER_TYPE_REC);
- lock->header.name = Str_SafeAsprintf(NULL, "MX_%p", mutex);
+
+ name = (*MXUserMX_NameRec)(mutex);
+
+ if (name == NULL) {
+ lock->header.name = Str_SafeAsprintf(NULL, "MX_%p", mutex);
+ } else {
+ lock->header.name = Str_SafeAsprintf(NULL, "%s *", name);
+ }
+
lock->header.rank = rank;
- lock->header.serialNumber = MXUserAllocSerialNumber();
+ lock->header.bits.serialNumber = MXUserAllocSerialNumber();
lock->header.dumpFunc = NULL;
lock->header.statsFunc = NULL;
@@ -1139,6 +1031,7 @@ MXUser_IncRefRecLock(MXUserRecLock *lock) // IN:
{
ASSERT(lock);
MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
+ ASSERT(Atomic_Read(&lock->refCount) > 0);
Atomic_Inc(&lock->refCount);
}
@@ -1169,43 +1062,3 @@ MXUser_DecRefRecLock(MXUserRecLock *lock) // IN:
MXUserCondDestroyRecLock(lock);
}
-
-
-#if defined(VMX86_VMX)
-#include "mutex.h"
-#include "mutexRankVMX.h"
-
-/*
- *----------------------------------------------------------------------------
- *
- * MXUser_InitFromMXRec --
- *
- * Initialize a MX_MutexRec lock and create a MXUserRecLock that binds
- * to it.
- *
- * Results:
- * Pointer to the MXUserRecLock.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------------
- */
-
-MXUserRecLock *
-MXUser_InitFromMXRec(const char *name, // IN:
- MX_MutexRec *mutex, // IN:
- MX_Rank rank, // IN:
- Bool isBelowBull) // IN:
-{
- MXUserRecLock *userLock;
-
- ASSERT(isBelowBull == (rank < RANK_userlevelLock));
-
- MX_InitLockRec(name, rank, mutex);
- userLock = MXUser_BindMXMutexRec(mutex, rank);
- ASSERT(userLock);
-
- return userLock;
-}
-#endif
diff --git a/open-vm-tools/lib/lock/ulSema.c b/open-vm-tools/lib/lock/ulSema.c
index 1263ef3e..af6a5132 100644
--- a/open-vm-tools/lib/lock/ulSema.c
+++ b/open-vm-tools/lib/lock/ulSema.c
@@ -20,9 +20,7 @@
#include <windows.h>
#else
#if defined(__APPLE__)
-#include <mach/mach_init.h>
-#include <mach/task.h>
-#include <mach/semaphore.h>
+#include <dispatch/dispatch.h>
#else
#if (_XOPEN_SOURCE < 600) && !defined(__FreeBSD__) && !defined(sun)
#undef _XOPEN_SOURCE
@@ -49,18 +47,18 @@
typedef HANDLE NativeSemaphore;
#else
#if defined(__APPLE__)
-typedef semaphore_t NativeSemaphore;
+/*
+ * The Mac OS implementation uses dispatch_semaphore_t instead of
+ * semaphore_t due to better performance in the uncontended case, by
+ * avoiding a system call. It, also, avoids weird error cases that
+ * resulted in bug 916600.
+ */
+typedef dispatch_semaphore_t NativeSemaphore;
#else
typedef sem_t NativeSemaphore;
#endif
#endif
-typedef struct
-{
- MXUserAcquisitionStats data;
- Atomic_Ptr histo;
-} MXUserAcquireStats;
-
struct MXUserSemaphore
{
MXUserHeader header;
@@ -101,7 +99,7 @@ struct MXUserSemaphore
#if defined(_WIN32)
static int
-MXUserInit(NativeSemaphore *sema) // IN:
+MXUserInit(NativeSemaphore *sema) // OUT:
{
*sema = Win32U_CreateSemaphore(NULL, 0, INT_MAX, NULL);
@@ -185,15 +183,17 @@ MXUserUp(NativeSemaphore *sema) // IN:
#elif defined(__APPLE__)
static int
-MXUserInit(NativeSemaphore *sema) // IN:
+MXUserInit(NativeSemaphore *sema) // OUT:
{
- return semaphore_create(mach_task_self(), sema, SYNC_POLICY_FIFO, 0);
+ *sema = dispatch_semaphore_create(0);
+ return *sema == NULL;
}
static int
MXUserDestroy(NativeSemaphore *sema) // IN:
{
- return semaphore_destroy(mach_task_self(), *sema);
+ dispatch_release(*sema);
+ return 0;
}
static int
@@ -201,63 +201,17 @@ MXUserTimedDown(NativeSemaphore *sema, // IN:
uint32 msecWait, // IN:
Bool *downOccurred) // OUT:
{
- uint64 nsecWait;
- VmTimeType before;
- kern_return_t err;
-
- ASSERT_ON_COMPILE(KERN_SUCCESS == 0);
-
- /*
- * Work in nanoseconds. Time the semaphore_timedwait operation in case
- * it is interrupted (KERN_ABORT). If it is, determine how much time is
- * necessary to fulfill the specified wait time and retry with a new
- * and appropriate timeout.
- */
-
- nsecWait = 1000000ULL * (uint64) msecWait;
- before = Hostinfo_SystemTimerNS();
-
- do {
- VmTimeType after;
- mach_timespec_t ts;
-
- ts.tv_sec = nsecWait / MXUSER_A_BILLION;
- ts.tv_nsec = nsecWait % MXUSER_A_BILLION;
-
- err = semaphore_timedwait(*sema, ts);
- after = Hostinfo_SystemTimerNS();
-
- if (err == KERN_SUCCESS) {
- *downOccurred = TRUE;
- } else {
- *downOccurred = FALSE;
-
- if (err == KERN_OPERATION_TIMED_OUT) {
- /* Really timed out; no down occurred, no error */
- err = KERN_SUCCESS;
- } else {
- if (err == KERN_ABORTED) {
- VmTimeType duration = after - before;
-
- if (duration < nsecWait) {
- nsecWait -= duration;
-
- before = after;
- } else {
- err = KERN_SUCCESS; // "timed out" anyway... no error
- }
- }
- }
- }
- } while (nsecWait && (err == KERN_ABORTED));
-
- return err;
+ int64 nsecWait = 1000000LL * (int64)msecWait;
+ dispatch_time_t deadline = dispatch_time(DISPATCH_TIME_NOW, nsecWait);
+ *downOccurred = dispatch_semaphore_wait(*sema, deadline) == 0;
+ return 0;
}
static int
MXUserDown(NativeSemaphore *sema) // IN:
{
- return semaphore_wait(*sema);
+ dispatch_semaphore_wait(*sema, DISPATCH_TIME_FOREVER);
+ return 0;
}
static int
@@ -265,24 +219,22 @@ MXUserTryDown(NativeSemaphore *sema, // IN:
Bool *downOccurred) // OUT:
{
/*
- * Use a wait for zero time to implement the try operation. This timed
- * down will either succeed immediately (down occurred), fail (something
- * terrible happened) or time out immediately (the down could not be
- * performed and that is OK).
+ * Provide 'try' semantics by requesting an immediate timeout.
*/
-
- return MXUserTimedDown(sema, 0, downOccurred);
+ *downOccurred = dispatch_semaphore_wait(*sema, DISPATCH_TIME_NOW) == 0;
+ return 0;
}
static int
MXUserUp(NativeSemaphore *sema) // IN:
{
- return semaphore_signal(*sema);
+ dispatch_semaphore_signal(*sema);
+ return 0;
}
#else
static int
-MXUserInit(NativeSemaphore *sema) // IN:
+MXUserInit(NativeSemaphore *sema) // OUT:
{
return (sem_init(sema, 0, 0) == -1) ? errno : 0;
}
@@ -360,7 +312,7 @@ MXUserTryDown(NativeSemaphore *sema, // IN:
*downOccurred = FALSE;
/*
- * If the error that occured indicates that the try operation cannot
+ * If the error that occurred indicates that the try operation cannot
* succeed (EAGAIN) or was interrupted (EINTR) suppress the error
* indicator as these are considered "normal", non-error cases.
*
@@ -427,10 +379,9 @@ MXUserStatsActionSema(MXUserHeader *header) // IN:
MXUserKitchen(&acquireStats->data, &contentionRatio, &isHot, &doLog);
if (isHot) {
- MXUserForceHisto(&acquireStats->histo,
- MXUSER_STAT_CLASS_ACQUISITION,
- MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
- MXUSER_DEFAULT_HISTO_DECADES);
+ MXUserForceAcquisitionHisto(&sema->acquireStatsMem,
+ MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
+ MXUSER_DEFAULT_HISTO_DECADES);
if (doLog) {
Log("HOT SEMAPHORE (%s); contention ratio %f\n",
@@ -467,7 +418,7 @@ MXUserDumpSemaphore(MXUserHeader *header) // IN:
Warning("\tsignature 0x%X\n", sema->header.signature);
Warning("\tname %s\n", sema->header.name);
Warning("\trank 0x%X\n", sema->header.rank);
- Warning("\tserial number %u\n", sema->header.serialNumber);
+ Warning("\tserial number %u\n", sema->header.bits.serialNumber);
Warning("\treference count %u\n", Atomic_Read(&sema->activeUserCount));
Warning("\taddress of native semaphore %p\n", &sema->nativeSemaphore);
@@ -477,7 +428,7 @@ MXUserDumpSemaphore(MXUserHeader *header) // IN:
/*
*-----------------------------------------------------------------------------
*
- * MXUserCreateSemaphore --
+ * MXUser_CreateSemaphore --
*
* Create a (counting) semaphore.
*
@@ -494,10 +445,9 @@ MXUserDumpSemaphore(MXUserHeader *header) // IN:
*-----------------------------------------------------------------------------
*/
-static MXUserSemaphore *
-MXUserCreateSemaphore(const char *userName, // IN:
- MX_Rank rank, // IN:
- Bool beSilent) // IN:
+MXUserSemaphore *
+MXUser_CreateSemaphore(const char *userName, // IN:
+ MX_Rank rank) // IN:
{
char *properName;
MXUserSemaphore *sema = Util_SafeCalloc(1, sizeof *sema);
@@ -514,23 +464,25 @@ MXUserCreateSemaphore(const char *userName, // IN:
sema->header.signature = MXUserGetSignature(MXUSER_TYPE_SEMA);
sema->header.name = properName;
sema->header.rank = rank;
- sema->header.serialNumber = MXUserAllocSerialNumber();
+ sema->header.bits.serialNumber = MXUserAllocSerialNumber();
sema->header.dumpFunc = MXUserDumpSemaphore;
- statsMode = beSilent ? 0 : MXUserStatsMode();
+ statsMode = MXUserStatsMode();
- if (statsMode == 0) {
+ switch (MXUserStatsMode()) {
+ case 0:
+ MXUserDisableStats(&sema->acquireStatsMem, NULL);
sema->header.statsFunc = NULL;
- Atomic_WritePtr(&sema->acquireStatsMem, NULL);
- } else {
- MXUserAcquireStats *acquireStats;
-
- acquireStats = Util_SafeCalloc(1, sizeof *acquireStats);
-
- MXUserAcquisitionStatsSetUp(&acquireStats->data);
+ break;
+ case 1:
+ case 2:
+ MXUserEnableStats(&sema->acquireStatsMem, NULL);
sema->header.statsFunc = MXUserStatsActionSema;
- Atomic_WritePtr(&sema->acquireStatsMem, acquireStats);
+ break;
+
+ default:
+ Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode);
}
MXUserAddToList(&sema->header);
@@ -547,56 +499,6 @@ MXUserCreateSemaphore(const char *userName, // IN:
/*
*-----------------------------------------------------------------------------
*
- * MXUser_CreateSemaphore --
- *
- * Create a (counting) semaphore. The semaphore may log messages,
- * statistics and contention information.
- *
- * Results:
- * A pointer to a semaphore.
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-MXUserSemaphore *
-MXUser_CreateSemaphore(const char *userName, // IN:
- MX_Rank rank) // IN:
-{
- return MXUserCreateSemaphore(userName, rank, FALSE);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * MXUser_CreateSemaphoreSilent --
- *
- * Create a (counting) semaphore specifying if the lock must always be
- * silent - never logging any messages. Silent locks will never
- * produce any statistics or contention information.
- *
- * Results:
- * A pointer to a semaphore.
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-MXUserSemaphore *
-MXUser_CreateSemaphoreSilent(const char *userName, // IN:
- MX_Rank rank) // IN:
-{
- return MXUserCreateSemaphore(userName, rank, TRUE);
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
* MXUser_DestroySemaphore --
*
* Destroy a semaphore
@@ -611,7 +513,7 @@ MXUser_CreateSemaphoreSilent(const char *userName, // IN:
*/
void
-MXUser_DestroySemaphore(MXUserSemaphore *sema) // IN:
+MXUser_DestroySemaphore(MXUserSemaphore *sema) // IN/OUT:
{
if (LIKELY(sema != NULL)) {
int err;
@@ -664,7 +566,7 @@ MXUser_DestroySemaphore(MXUserSemaphore *sema) // IN:
* on a semaphore.
*
* Results:
- * The count will be decremented; a sleep may occur until the decement
+ * The count will be decremented; a sleep may occur until the decrement
* is possible.
*
* Side effects:
@@ -835,7 +737,7 @@ MXUser_TimedDownSemaphore(MXUserSemaphore *sema, // IN/OUT:
*
* NOTE:
* A "TryAcquire" does not rank check should the down operation succeed.
- * This duplicates the behavor of MX semaphores.
+ * This duplicates the behavior of MX semaphores.
*
*-----------------------------------------------------------------------------
*/
diff --git a/open-vm-tools/lib/lock/ulStats.c b/open-vm-tools/lib/lock/ulStats.c
index a19426c3..474aedc7 100644
--- a/open-vm-tools/lib/lock/ulStats.c
+++ b/open-vm-tools/lib/lock/ulStats.c
@@ -35,7 +35,7 @@
static double mxUserContentionRatioFloor = 0.0; // always "off"
static uint64 mxUserContentionCountFloor = 0; // always "off"
-VmTimeType mxUserContentionDurationFloor = 0; // always "off"
+static uint64 mxUserContentionDurationFloor = 0; // always "off"
static Atomic_Ptr mxLockMemPtr; // internal singleton lock
static ListItem *mxUserLockList; // list of all MXUser locks
@@ -83,7 +83,7 @@ static void (*mxUserStatsFunc)(void *context,
*/
void
-MXUserAddToList(MXUserHeader *header) // IN:
+MXUserAddToList(MXUserHeader *header) // IN/OUT:
{
MXRecLock *listLock = MXUserInternalSingleton(&mxLockMemPtr);
@@ -114,7 +114,7 @@ MXUserAddToList(MXUserHeader *header) // IN:
*/
void
-MXUserRemoveFromList(MXUserHeader *header) // IN:
+MXUserRemoveFromList(MXUserHeader *header) // IN/OUT:
{
MXRecLock *listLock = MXUserInternalSingleton(&mxLockMemPtr);
@@ -233,7 +233,7 @@ MXUserHistoSetUp(char *typeName, // type (name) of histogram
*/
void
-MXUserHistoTearDown(MXUserHisto *histo) // IN:
+MXUserHistoTearDown(MXUserHisto *histo) // IN/OUT:
{
if (histo != NULL) {
free(histo->typeName);
@@ -371,8 +371,8 @@ MXUserHistoDump(MXUserHisto *histo, // IN:
i = Str_Sprintf(mxUserHistoLine, mxUserMaxLineLength,
"MXUser: h l=%u t=%s min=%"FMT64"u max=%"FMT64"u\n",
- header->serialNumber, histo->typeName, histo->minValue,
- histo->maxValue);
+ header->bits.serialNumber, histo->typeName,
+ histo->minValue, histo->maxValue);
/*
* The terminating "\n\0" will be overwritten each time a histogram
@@ -413,7 +413,7 @@ MXUserHistoDump(MXUserHisto *histo, // IN:
MXUserStatsLog("%s", mxUserHistoLine);
i = Str_Sprintf(mxUserHistoLine, mxUserMaxLineLength,
- "MXUser: ht l=%u t=%s\n", header->serialNumber,
+ "MXUser: ht l=%u t=%s\n", header->bits.serialNumber,
histo->typeName);
p = &mxUserHistoLine[i - 1];
@@ -587,7 +587,7 @@ MXUserDumpBasicStats(MXUserBasicStats *stats, // IN:
MXUserStatsLog("MXUser: e l=%u t=%s c=%"FMT64"u min=%"FMT64"u "
"max=%"FMT64"u mean=%"FMT64"u sd=%"FMT64"u\n",
- header->serialNumber, stats->typeName,
+ header->bits.serialNumber, stats->typeName,
stats->numSamples, stats->minTime, stats->maxTime,
stats->timeSum/stats->numSamples, stdDev);
}
@@ -640,6 +640,9 @@ MXUserAcquisitionStatsSetUp(MXUserAcquisitionStats *stats) // IN/OUT:
{
MXUserBasicStatsSetUp(&stats->basicStats, MXUSER_STAT_CLASS_ACQUISITION);
+ stats->contentionRatioFloor = mxUserContentionRatioFloor;
+ stats->contentionCountFloor = mxUserContentionCountFloor;
+ stats->contentionDurationFloor = mxUserContentionDurationFloor;
stats->numAttempts = 0;
stats->numSuccesses = 0;
stats->numSuccessesContended = 0;
@@ -717,7 +720,7 @@ MXUserDumpAcquisitionStats(MXUserAcquisitionStats *stats, // IN:
MXUserStatsLog("MXUser: ce l=%u a=%"FMT64"u s=%"FMT64"u sc=%"FMT64"u "
"sct=%"FMT64"u t=%"FMT64"u\n",
- header->serialNumber,
+ header->bits.serialNumber,
stats->numAttempts,
stats->numSuccesses,
stats->numSuccessesContended,
@@ -777,7 +780,7 @@ MXUserKitchen(MXUserAcquisitionStats *stats, // IN:
* How much "heat" is this lock generating?
*/
- if (stats->numAttempts < mxUserContentionCountFloor) {
+ if (stats->numAttempts < stats->contentionCountFloor) {
*contentionRatio = 0.0;
} else {
double basic;
@@ -810,14 +813,14 @@ MXUserKitchen(MXUserAcquisitionStats *stats, // IN:
* side effect that no logging of "temperature changes" is done.
*/
- if (mxUserContentionCountFloor == 0) { // never "hot"
+ if (stats->contentionCountFloor == 0) { // never "hot"
*isHot = FALSE;
*doLog = FALSE;
return;
}
- if (mxUserContentionCountFloor == ~((uint64) 0)) { // always "hot"; no logging
+ if (stats->contentionCountFloor == ~((uint64) 0)) { // always "hot"; no logging
*isHot = TRUE;
*doLog = FALSE;
@@ -828,12 +831,11 @@ MXUserKitchen(MXUserAcquisitionStats *stats, // IN:
* Did the thermostat trip?
*/
- ASSERT((mxUserContentionRatioFloor > 0.0) && (mxUserContentionRatioFloor <= 1.0));
- if (*contentionRatio > mxUserContentionRatioFloor) { // Yes
+ if (*contentionRatio > stats->contentionRatioFloor) { // Yes
*isHot = TRUE;
*doLog = TRUE;
- } else { // No
+ } else { // No
*doLog = FALSE;
*isHot = FALSE;
}
@@ -886,7 +888,7 @@ MXUser_StatisticsControl(double contentionRatioFloor, // IN:
*-----------------------------------------------------------------------------
*/
-void
+static INLINE void
MXUserForceHisto(Atomic_Ptr *histoPtr, // IN/OUT:
char *typeName, // IN:
uint64 minValue, // IN:
@@ -899,8 +901,7 @@ MXUserForceHisto(Atomic_Ptr *histoPtr, // IN/OUT:
ptr = MXUserHistoSetUp(typeName, minValue, decades);
- before = (MXUserHisto *) Atomic_ReadIfEqualWritePtr(histoPtr, NULL,
- (void *) ptr);
+ before = Atomic_ReadIfEqualWritePtr(histoPtr, NULL, (void *) ptr);
if (before) {
MXUserHistoTearDown(ptr);
@@ -908,6 +909,71 @@ MXUserForceHisto(Atomic_Ptr *histoPtr, // IN/OUT:
}
}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserForceAcquisitionHisto --
+ *
+ * Force acquisition histogram taking.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * Memory is allocated.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUserForceAcquisitionHisto(Atomic_Ptr *mem, // IN/OUT:
+ uint64 minValue, // IN:
+ uint32 decades) // IN:
+{
+ MXUserAcquireStats *acquireStats = Atomic_ReadPtr(mem);
+
+ if (LIKELY(acquireStats != NULL)) {
+ MXUserForceHisto(&acquireStats->histo, MXUSER_STAT_CLASS_ACQUISITION,
+ minValue, decades);
+ }
+
+ return (acquireStats != NULL);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserForceHeldHisto --
+ *
+ * Force held histogram taking.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * Memory is allocated.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUserForceHeldHisto(Atomic_Ptr *mem, // IN/OUT:
+ uint64 minValue, // IN:
+ uint32 decades) // IN:
+{
+ MXUserHeldStats *heldStats = Atomic_ReadPtr(mem);
+
+ if (LIKELY(heldStats != NULL)) {
+ MXUserForceHisto(&heldStats->histo, MXUSER_STAT_CLASS_HELD,
+ minValue, decades);
+ }
+
+ return (heldStats != NULL);
+}
+
+
/*
*-----------------------------------------------------------------------------
*
@@ -916,7 +982,7 @@ MXUserForceHisto(Atomic_Ptr *histoPtr, // IN/OUT:
* What's to be done with statistics?
*
* Results:
- * 0 Statstics are disabled
+ * 0 Statistics are disabled
* 1 Collect statistics without tracking held times
* 2 Collect statistics with track held times
*
@@ -1021,12 +1087,12 @@ MXUser_PerLockData(void)
MXUserHeader *header = LIST_CONTAINER(entry, MXUserHeader, item);
/* Log the ID information for a lock that did exist previously */
- if (header->serialNumber > lastReportedSerialNumber) {
+ if (header->bits.serialNumber > lastReportedSerialNumber) {
MXUserStatsLog("MXUser: n n=%s l=%d r=0x%x\n", header->name,
- header->serialNumber, header->rank);
+ header->bits.serialNumber, header->rank);
- if (header->serialNumber > highestSerialNumber) {
- highestSerialNumber = header->serialNumber;
+ if (header->bits.serialNumber > highestSerialNumber) {
+ highestSerialNumber = header->bits.serialNumber;
}
}
@@ -1059,7 +1125,7 @@ MXUser_PerLockData(void)
* As above.
*
* Side effects:
- * None.
+ * Panic if too many serial numbers are generated (PR 1309544).
*
*-----------------------------------------------------------------------------
*/
@@ -1067,7 +1133,219 @@ MXUser_PerLockData(void)
uint32
MXUserAllocSerialNumber(void)
{
+ uint32 value;
+
static Atomic_uint32 firstFreeSerialNumber = { 1 }; // must start not zero
- return Atomic_ReadInc32(&firstFreeSerialNumber);
+ value = Atomic_ReadInc32(&firstFreeSerialNumber);
+
+ /*
+ * The serial number must be able to fit into the serial number field
+ * (see ulInt.h).
+ */
+
+ if (value > 0xFFFFFF) {
+ Panic("%s: too many locks!\n", __FUNCTION__);
+ }
+
+ return value;
}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserSetContentionRatioFloor
+ *
+ * Set acquisition tracking contention ratio floor.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUserSetContentionRatioFloor(Atomic_Ptr *mem, // IN/OUT:
+ double ratio) // IN:
+{
+ MXUserAcquireStats *acquireStats = Atomic_ReadPtr(mem);
+
+ if (LIKELY(acquireStats != NULL)) {
+ acquireStats->data.contentionRatioFloor = ratio;
+ }
+
+ return (acquireStats != NULL);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserSetContentionCountFloor
+ *
+ * Set acquisition tracking contention count floor.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUserSetContentionCountFloor(Atomic_Ptr *mem, // IN/OUT:
+ uint64 count) // IN:
+{
+ MXUserAcquireStats *acquireStats = Atomic_ReadPtr(mem);
+
+ if (LIKELY(acquireStats != NULL)) {
+ acquireStats->data.contentionCountFloor = count;
+ }
+
+ return (acquireStats != NULL);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserSetContentionDurationFloor
+ *
+ * Set acquisition tracking contention duration floor.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUserSetContentionDurationFloor(Atomic_Ptr *mem, // IN/OUT:
+ uint64 count) // IN:
+{
+ MXUserAcquireStats *acquireStats = Atomic_ReadPtr(mem);
+
+ if (LIKELY(acquireStats != NULL)) {
+ acquireStats->data.contentionDurationFloor = count;
+ }
+
+ return (acquireStats != NULL);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserDisableStats
+ *
+ * Disable any statisitics collection. This should only be used
+ * immediately after a lock is created.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUserDisableStats(Atomic_Ptr *acquisitionMem, // IN/OPT:
+ Atomic_Ptr *heldMem) // IN/OPT:
+{
+ if (acquisitionMem != NULL) {
+ MXUserAcquireStats *acquireStats = Atomic_ReadPtr(acquisitionMem);
+
+ if (UNLIKELY(acquireStats != NULL)) {
+ MXUserAcquisitionStatsTearDown(&acquireStats->data);
+ MXUserHistoTearDown(Atomic_ReadPtr(&acquireStats->histo));
+
+ free(acquireStats);
+ }
+
+ Atomic_WritePtr(acquisitionMem, NULL);
+ }
+
+ if (heldMem != NULL) {
+ MXUserHeldStats *heldStats = Atomic_ReadPtr(heldMem);
+
+ if (UNLIKELY(heldStats != NULL)) {
+ MXUserBasicStatsTearDown(&heldStats->data);
+ MXUserHistoTearDown(Atomic_ReadPtr(&heldStats->histo));
+
+ free(heldStats);
+ }
+
+ Atomic_WritePtr(heldMem, NULL);
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserEnableStats
+ *
+ * Enable statisitics collection
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUserEnableStats(Atomic_Ptr *acquisitionMem, // IN/OPT:
+ Atomic_Ptr *heldMem) // IN/OPT:
+{
+
+ if (acquisitionMem != NULL) {
+ MXUserAcquireStats *acquireStats = Atomic_ReadPtr(acquisitionMem);
+
+ if (LIKELY(acquireStats == NULL)) {
+ MXUserAcquireStats *before;
+
+ acquireStats = Util_SafeCalloc(1, sizeof *acquireStats);
+ MXUserAcquisitionStatsSetUp(&acquireStats->data);
+
+ before = Atomic_ReadIfEqualWritePtr(acquisitionMem, NULL,
+ (void *) acquireStats);
+
+ if (before) {
+ free(acquireStats);
+ }
+ }
+ }
+
+ if (heldMem != NULL) {
+ MXUserHeldStats *heldStats = Atomic_ReadPtr(heldMem);
+
+ if (LIKELY(heldStats == NULL)) {
+ MXUserHeldStats *before;
+
+ heldStats = Util_SafeCalloc(1, sizeof *heldStats);
+ MXUserBasicStatsSetUp(&heldStats->data, MXUSER_STAT_CLASS_HELD);
+
+ before = Atomic_ReadIfEqualWritePtr(heldMem, NULL,
+ (void *) heldStats);
+
+ if (before) {
+ free(heldStats);
+ }
+ }
+ }
+}
+
diff --git a/open-vm-tools/lib/message/message.c b/open-vm-tools/lib/message/message.c
index 506fe423..53b13223 100644
--- a/open-vm-tools/lib/message/message.c
+++ b/open-vm-tools/lib/message/message.c
@@ -75,52 +75,36 @@ extern "C" {
# define MESSAGE_LOG(...)
#endif
-/* The channel object */
-struct Message_Channel {
- /* Identifier */
- uint16 id;
-
- /* Reception buffer */
- /* Data */
- unsigned char *in;
- /* Allocated size */
- size_t inAlloc;
-
- /* The cookie */
- uint32 cookieHigh;
- uint32 cookieLow;
-};
-
/*
*-----------------------------------------------------------------------------
*
- * Message_Open --
+ * Message_OpenAllocated --
*
- * Open a communication channel
+ * Open a communication channel using an allocated, but unitialized
+ * Message_Channel structure. A receive buffer may be optionally
+ * specified with a given size. If a message larger than this
+ * buffer is received the communication will be aborted. If no
+ * receiver buffer is specified, one will be dynamically allocated
+ * to size. When finished with the channel, Message_CloseAllocated
+ * should be called.
*
* Result:
- * An allocated Message_Channel on success
- * NULL on failure
+ * TRUE on success, FALSE on failure.
*
* Side-effects:
- * None
+ * See above.
*
*-----------------------------------------------------------------------------
*/
-Message_Channel *
-Message_Open(uint32 proto) // IN
+Bool
+Message_OpenAllocated(uint32 proto, Message_Channel *chan,
+ char *receiveBuffer, size_t receiveBufferSize)
{
- Message_Channel *chan;
uint32 flags;
Backdoor_proto bp;
- chan = (Message_Channel *)malloc(sizeof(*chan));
- if (chan == NULL) {
- goto error_quit;
- }
-
flags = GUESTMSG_FLAG_COOKIE;
retry:
/* IN: Type */
@@ -140,7 +124,7 @@ retry:
}
MESSAGE_LOG("Message: Unable to open a communication channel\n");
- goto error_quit;
+ return FALSE;
}
/* OUT: Id and cookie */
@@ -149,15 +133,43 @@ retry:
chan->cookieLow = bp.out.di.word;
/* Initialize the channel */
- chan->in = NULL;
- chan->inAlloc = 0;
+ chan->in = (unsigned char *)receiveBuffer;
+ chan->inAlloc = receiveBufferSize;
- return chan;
+ ASSERT((receiveBuffer == NULL) == (receiveBufferSize == 0));
+ chan->inPreallocated = receiveBuffer != NULL;
-error_quit:
- free(chan);
- chan = NULL;
- return NULL;
+ return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Message_Open --
+ *
+ * Open a communication channel
+ *
+ * Result:
+ * An allocated Message_Channel on success
+ * NULL on failure
+ *
+ * Side-effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Message_Channel *
+Message_Open(uint32 proto) // IN
+{
+ Message_Channel *chan = malloc(sizeof *chan);
+
+ if (chan != NULL && !Message_OpenAllocated(proto, chan, NULL, 0)) {
+ free(chan);
+ chan = NULL;
+ }
+ return chan;
}
@@ -381,15 +393,20 @@ retry:
* a C string instead. --hpreg
*/
if (myBufSize + 1 > chan->inAlloc) {
- myBuf = (unsigned char *)realloc(chan->in, myBufSize + 1);
- if (myBuf == NULL) {
- MESSAGE_LOG("Message: Not enough memory to receive a message over "
+ if (chan->inPreallocated) {
+ MESSAGE_LOG("Message: Buffer too small to receive a message over "
"the communication channel %u\n", chan->id);
goto error_quit;
+ } else {
+ myBuf = (unsigned char *)realloc(chan->in, myBufSize + 1);
+ if (myBuf == NULL) {
+ MESSAGE_LOG("Message: Not enough memory to receive a message over "
+ "the communication channel %u\n", chan->id);
+ goto error_quit;
+ }
+ chan->in = myBuf;
+ chan->inAlloc = myBufSize + 1;
}
-
- chan->in = myBuf;
- chan->inAlloc = myBufSize + 1;
}
*bufSize = myBufSize;
myBuf = *buf = chan->in;
@@ -556,9 +573,10 @@ error_quit:
/*
*-----------------------------------------------------------------------------
*
- * Message_Close --
+ * Message_CloseAllocated --
*
- * Close a communication channel
+ * Close a communication channel that had been allocated by the
+ * caller. (For use with Message_OpenAllocated.)
*
* Result:
* TRUE on success, the channel is destroyed
@@ -571,7 +589,7 @@ error_quit:
*/
Bool
-Message_Close(Message_Channel *chan) // IN/OUT
+Message_CloseAllocated(Message_Channel *chan) // IN/OUT
{
Backdoor_proto bp;
Bool ret = TRUE;
@@ -593,9 +611,37 @@ Message_Close(Message_Channel *chan) // IN/OUT
ret = FALSE;
}
- free(chan->in);
+ if (!chan->inPreallocated) {
+ free(chan->in);
+ }
chan->in = NULL;
+ return ret;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Message_Close --
+ *
+ * Close a communication channel.
+ *
+ * Result:
+ * TRUE on success, the channel is destroyed
+ * FALSE on failure
+ *
+ * Side-effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+Message_Close(Message_Channel *chan) // IN/OUT
+{
+ Bool ret = Message_CloseAllocated(chan);
+
free(chan);
return ret;
}
diff --git a/open-vm-tools/lib/misc/Makefile.am b/open-vm-tools/lib/misc/Makefile.am
index f7c708b5..8373864f 100644
--- a/open-vm-tools/lib/misc/Makefile.am
+++ b/open-vm-tools/lib/misc/Makefile.am
@@ -43,6 +43,7 @@ libMisc_la_SOURCES += posixDlopen.c
libMisc_la_SOURCES += posixPosix.c
libMisc_la_SOURCES += posixPwd.c
libMisc_la_SOURCES += random.c
+libMisc_la_SOURCES += sleep.c
libMisc_la_SOURCES += timeutil.c
libMisc_la_SOURCES += util_misc.c
libMisc_la_SOURCES += utilMem.c
diff --git a/open-vm-tools/lib/misc/Makefile.in b/open-vm-tools/lib/misc/Makefile.in
index c8df02fe..41f117a4 100644
--- a/open-vm-tools/lib/misc/Makefile.in
+++ b/open-vm-tools/lib/misc/Makefile.in
@@ -67,8 +67,8 @@ am_libMisc_la_OBJECTS = atomic.lo base64.lo codeset.lo codesetBase.lo \
hostinfo.lo hostinfoHV.lo hostinfoPosix.lo hostname.lo \
hostType.lo idLinux.lo iovector.lo logFixed.lo machineID.lo \
miscSolaris.lo msgfmt.lo msgList.lo posixDlopen.lo \
- posixPosix.lo posixPwd.lo random.lo timeutil.lo util_misc.lo \
- utilMem.lo vmstdio.lo strutil.lo vthreadBase.lo
+ posixPosix.lo posixPwd.lo random.lo sleep.lo timeutil.lo \
+ util_misc.lo utilMem.lo vmstdio.lo strutil.lo vthreadBase.lo
libMisc_la_OBJECTS = $(am_libMisc_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
@@ -281,8 +281,8 @@ libMisc_la_SOURCES = atomic.c base64.c codeset.c codesetBase.c \
hostinfo.c hostinfoHV.c hostinfoPosix.c hostname.c hostType.c \
idLinux.c iovector.c logFixed.c machineID.c miscSolaris.c \
msgfmt.c msgList.c posixDlopen.c posixPosix.c posixPwd.c \
- random.c timeutil.c util_misc.c utilMem.c vmstdio.c strutil.c \
- vthreadBase.c
+ random.c sleep.c timeutil.c util_misc.c utilMem.c vmstdio.c \
+ strutil.c vthreadBase.c
all: all-am
.SUFFIXES:
@@ -359,6 +359,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/posixPosix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/posixPwd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sleep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strutil.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timeutil.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utilMem.Plo@am__quote@
diff --git a/open-vm-tools/lib/misc/base64.c b/open-vm-tools/lib/misc/base64.c
index 77e7576d..08795f8e 100644
--- a/open-vm-tools/lib/misc/base64.c
+++ b/open-vm-tools/lib/misc/base64.c
@@ -131,16 +131,16 @@ static const signed char base64Reverse[256] = {
Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
- 0 A 17 R 34 i 51 z
- 1 B 18 S 35 j 52 0
- 2 C 19 T 36 k 53 1
- 3 D 20 U 37 l 54 2
- 4 E 21 V 38 m 55 3
- 5 F 22 W 39 n 56 4
- 6 G 23 X 40 o 57 5
- 7 H 24 Y 41 p 58 6
- 8 I 25 Z 42 q 59 7
- 9 J 26 a 43 r 60 8
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
@@ -515,10 +515,10 @@ Base64_DecodedLength(char const *src, // IN:
// PR 303173 - do the following check to avoid a negative value returned
// from this function. Note: length can only be in a multiple of 3
if (length > 2) {
- if (src[srcLength-1] == '=') {
+ if (src[srcLength - 1] == '=') {
length--;
}
- if (src[srcLength-2] == '=') {
+ if (src[srcLength - 2] == '=') {
length--;
}
}
@@ -557,7 +557,7 @@ Base64_EasyEncode(const uint8 *src, // IN: data to encode
size = Base64_EncodedLength(src, srcLength);
- *target = (char *) malloc(size);
+ *target = malloc(size);
if (!*target) {
goto exit;
@@ -611,7 +611,7 @@ Base64_EasyDecode(const char *src, // IN: data to decode
theDataSize = Base64_DecodedLength(src, strlen(src));
- theData = (uint8 *) malloc(theDataSize);
+ theData = malloc(theDataSize);
if (!theData) {
goto exit;
@@ -635,3 +635,48 @@ exit:
return succeeded;
}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Base64_DecodeFixed --
+ *
+ * Base64-decode 'src' into a preallocated, fixed sized buffer.
+ *
+ * Results:
+ * TRUE outBuf is populated with the decoded string
+ * FALSE Decoding or memory allocation failed.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+Base64_DecodeFixed(const char *src, // IN: data to decode
+ char *outBuf, // OUT: decoded data
+ size_t outBufSize) // IN: data size
+{
+ Bool success;
+ uint8 *theData;
+ size_t theDataSize;
+
+ ASSERT(src);
+ ASSERT(outBuf);
+
+ success = Base64_EasyDecode(src, &theData, &theDataSize);
+
+ if (success) {
+ success = (theDataSize <= outBufSize);
+
+ if (success) {
+ memcpy(outBuf, theData, theDataSize);
+ }
+
+ free(theData);
+ }
+
+ return success;
+}
diff --git a/open-vm-tools/lib/misc/codeset.c b/open-vm-tools/lib/misc/codeset.c
index e227895a..b420abc7 100644
--- a/open-vm-tools/lib/misc/codeset.c
+++ b/open-vm-tools/lib/misc/codeset.c
@@ -248,7 +248,7 @@ CodeSetGetModulePath(uint32 priv)
#else
#if defined(VMX86_SERVER)
- if (HostType_OSIsPureVMK()) {
+ if (HostType_OSIsVMK()) {
goto exit;
}
#endif
@@ -1098,7 +1098,7 @@ CodeSet_GenericToGeneric(const char *codeIn, // IN
const char *codeOut, // IN
unsigned int flags, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
DynBuf db;
Bool ok;
@@ -1176,7 +1176,7 @@ Bool
CodeSet_Utf8ToCurrent(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
#if !defined(CURRENT_IS_UTF8)
DynBuf db;
@@ -1225,7 +1225,7 @@ Bool
CodeSet_CurrentToUtf8(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
#if !defined(CURRENT_IS_UTF8)
DynBuf db;
@@ -1311,7 +1311,7 @@ Bool
CodeSet_Utf16leToUtf8(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
DynBuf db;
Bool ok;
@@ -1355,7 +1355,7 @@ Bool
CodeSet_Utf8ToUtf16le(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
DynBuf db;
Bool ok;
@@ -1399,7 +1399,7 @@ Bool
CodeSet_Utf8FormDToUtf8FormC(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
/*
* Fallback if necessary.
@@ -1448,7 +1448,7 @@ Bool
CodeSet_Utf8FormCToUtf8FormD(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
/*
* Fallback if necessary.
@@ -1495,7 +1495,7 @@ Bool
CodeSet_CurrentToUtf16le(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
DynBuf db;
Bool ok;
@@ -1538,7 +1538,7 @@ Bool
CodeSet_Utf16leToCurrent(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
DynBuf db;
Bool ok;
@@ -1581,7 +1581,7 @@ Bool
CodeSet_Utf16beToCurrent(const char *bufIn, // IN
size_t sizeIn, // IN
char **bufOut, // OUT
- size_t *sizeOut) // OUT
+ size_t *sizeOut) // OUT/OPT
{
DynBuf db;
Bool ok;
diff --git a/open-vm-tools/lib/misc/codesetBase.c b/open-vm-tools/lib/misc/codesetBase.c
index 08f3f61b..18c21c4e 100644
--- a/open-vm-tools/lib/misc/codesetBase.c
+++ b/open-vm-tools/lib/misc/codesetBase.c
@@ -289,7 +289,7 @@ CodeSet_UTF8ToUTF32(const char *utf8, // IN:
p = (char *) utf8;
end = p + strlen(utf8);
- ptr = Util_SafeMalloc(sizeof(*ptr) * (codePoints + 1));
+ ptr = Util_SafeMalloc(sizeof *ptr * (codePoints + 1));
*utf32 = (char *) ptr;
while (p < end) {
diff --git a/open-vm-tools/lib/misc/codesetOld.c b/open-vm-tools/lib/misc/codesetOld.c
index 28d3eecb..74ed359d 100644
--- a/open-vm-tools/lib/misc/codesetOld.c
+++ b/open-vm-tools/lib/misc/codesetOld.c
@@ -95,7 +95,7 @@ swab(const void *__restrict src, // IN/OUT
uint16 *q = dest;
ssize_t i;
- for (i = 0; i < nbytes / sizeof(*p); i++) {
+ for (i = 0; i < nbytes / sizeof *p; i++) {
q[i] = Bswap16(p[i]);
}
}
@@ -726,7 +726,7 @@ CodeSetOld_GetCurrentCodeSet(void)
#elif defined(_WIN32)
static char ret[20]; // max is "windows-4294967296"
if (ret[0] == '\0') {
- Str_Sprintf(ret, sizeof(ret), "windows-%u", GetACP());
+ Str_Sprintf(ret, sizeof ret, "windows-%u", GetACP());
}
return ret;
@@ -2154,8 +2154,8 @@ GetInvalidCharsFlag(void)
* Try calling GetVersionEx using the OSVERSIONINFOEX structure.
*/
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ ZeroMemory(&osvi, sizeof osvi);
+ osvi.dwOSVersionInfoSize = sizeof osvi;
/*
* Starting with msvc-12.0 / SDK v8.1 GetVersionEx is deprecated.
diff --git a/open-vm-tools/lib/misc/dynbuf.c b/open-vm-tools/lib/misc/dynbuf.c
index 95b37559..31bd923a 100644
--- a/open-vm-tools/lib/misc/dynbuf.c
+++ b/open-vm-tools/lib/misc/dynbuf.c
@@ -102,7 +102,7 @@ DynBuf_Destroy(DynBuf *b) // IN/OUT:
*/
void *
-DynBuf_AllocGet(DynBuf const *b) // IN
+DynBuf_AllocGet(DynBuf const *b) // IN:
{
void *new_data;
ASSERT(b);
@@ -134,9 +134,9 @@ DynBuf_AllocGet(DynBuf const *b) // IN
*/
void
-DynBuf_Attach(DynBuf *b, // IN
- size_t size, // IN
- void *data) // IN
+DynBuf_Attach(DynBuf *b, // IN/OUT:
+ size_t size, // IN:
+ void *data) // IN:
{
ASSERT(b);
ASSERT((size == 0) == (data == NULL));
@@ -165,7 +165,7 @@ DynBuf_Attach(DynBuf *b, // IN
*/
void *
-DynBuf_Detach(DynBuf *b) // IN
+DynBuf_Detach(DynBuf *b) // IN/OUT:
{
void *data;
@@ -197,7 +197,7 @@ DynBuf_Detach(DynBuf *b) // IN
*/
static Bool
-DynBufRealloc(DynBuf *b, // IN:
+DynBufRealloc(DynBuf *b, // IN/OUT:
size_t newAllocated) // IN:
{
void *new_data;
@@ -237,7 +237,7 @@ DynBufRealloc(DynBuf *b, // IN:
*/
Bool
-DynBuf_Enlarge(DynBuf *b, // IN:
+DynBuf_Enlarge(DynBuf *b, // IN/OUT:
size_t minSize) // IN:
{
size_t newAllocated;
@@ -305,9 +305,9 @@ DynBuf_Enlarge(DynBuf *b, // IN:
*/
Bool
-DynBuf_Append(DynBuf *b, // IN
- void const *data, // IN
- size_t size) // IN
+DynBuf_Append(DynBuf *b, // IN/OUT:
+ void const *data, // IN:
+ size_t size) // IN:
{
size_t new_size;
@@ -358,11 +358,11 @@ DynBuf_Append(DynBuf *b, // IN
*/
void
-DynBuf_SafeInternalAppend(DynBuf *b, // IN
- void const *data, // IN
- size_t size, // IN
- char const *file, // IN
- unsigned int lineno) // IN
+DynBuf_SafeInternalAppend(DynBuf *b, // IN/OUT:
+ void const *data, // IN:
+ size_t size, // IN:
+ char const *file, // IN:
+ unsigned int lineno) // IN:
{
if (!DynBuf_Append(b, data, size)) {
Panic("Unrecoverable memory allocation failure at %s:%u\n",
@@ -389,7 +389,7 @@ DynBuf_SafeInternalAppend(DynBuf *b, // IN
*/
Bool
-DynBuf_Trim(DynBuf *b) // IN
+DynBuf_Trim(DynBuf *b) // IN/OUT:
{
ASSERT(b);
@@ -402,7 +402,7 @@ DynBuf_Trim(DynBuf *b) // IN
*
* DynBuf_Copy --
*
- * Copies all data and metadata from src dynbuff to dest dynbuf.
+ * Copies all data and metadata from src dynbuf to dest dynbuf.
*
* Dest should be an initialized DynBuf of alloced length zero
* to prevent memory leaks.
@@ -417,8 +417,8 @@ DynBuf_Trim(DynBuf *b) // IN
*/
Bool
-DynBuf_Copy(DynBuf *src, // IN
- DynBuf *dest) // OUT
+DynBuf_Copy(DynBuf *src, // IN:
+ DynBuf *dest) // OUT:
{
ASSERT(src);
ASSERT(dest);
diff --git a/open-vm-tools/lib/misc/escape.c b/open-vm-tools/lib/misc/escape.c
index 478b1f4e..eb28c26f 100644
--- a/open-vm-tools/lib/misc/escape.c
+++ b/open-vm-tools/lib/misc/escape.c
@@ -24,6 +24,8 @@
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include "vmware.h"
#include "dynbuf.h"
@@ -292,6 +294,52 @@ nem:
/*
*-----------------------------------------------------------------------------
*
+ * Escape_UndoFixed --
+ *
+ * Unescape a buffer into a fixed sized, preallocated buffer.
+ *
+ * Results:
+ * TRUE The unescaped NUL terminated data is in bufOut upon success.
+ * FALSE Escape or memory allocation failure.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+Escape_UndoFixed(char escByte, // IN: escape byte
+ void const *bufIn, // IN: string to be escaped
+ size_t bufInSize, // IN: uint32 - fixed size for Python
+ void *bufOut, // IN/OUT: preallocated output buffer
+ size_t bufOutSize) // IN: uint32 - fixed size for Python
+{
+ Bool success;
+ size_t sizeOut = 0;
+ void *result = Escape_Undo(escByte, bufIn, bufInSize, &sizeOut);
+
+ if (result == NULL) {
+ success = FALSE;
+ } else {
+ size_t strLen = sizeOut + 1; // Include NUL
+
+ success = (strLen <= bufOutSize);
+
+ if (success) {
+ memcpy(bufOut, result, strLen);
+ }
+
+ free(result);
+ }
+
+ return success;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* Escape_AnsiToUnix --
*
* Convert any occurrence of \r\n into \n --hpreg
diff --git a/open-vm-tools/lib/misc/hashTable.c b/open-vm-tools/lib/misc/hashTable.c
index a0abfee6..7a18bb99 100644
--- a/open-vm-tools/lib/misc/hashTable.c
+++ b/open-vm-tools/lib/misc/hashTable.c
@@ -94,10 +94,6 @@ struct HashTable {
* Local functions
*/
-static HashTableEntry *HashTableLookup(HashTable *ht,
- const void *keyStr,
- uint32 hash);
-
HashTableEntry *HashTableLookupOrInsert(HashTable *ht,
const void *keyStr,
void *clientData);
@@ -243,7 +239,6 @@ HashTable_Alloc(uint32 numEntries, // IN: must be a power of 2
(keyType & HASH_TYPE_MASK) == HASH_ISTRING_KEY));
ht = Util_SafeMalloc(sizeof *ht);
- VERIFY(ht);
ht->numBits = lssb32_0(numEntries);
ht->numEntries = numEntries;
@@ -379,13 +374,14 @@ HashTable_Clear(HashTable *ht) // IN/OUT:
void
HashTable_Free(HashTable *ht) // IN/OUT:
{
- ASSERT(ht);
- ASSERT(!ht->atomic);
+ if (ht != NULL) {
+ ASSERT(!ht->atomic);
- HashTableClearInternal(ht);
+ HashTableClearInternal(ht);
- free(ht->buckets);
- free(ht);
+ free(ht->buckets);
+ free(ht);
+ }
}
@@ -410,12 +406,12 @@ HashTable_Free(HashTable *ht) // IN/OUT:
void
HashTable_FreeUnsafe(HashTable *ht) // IN/OUT:
{
- ASSERT(ht);
-
- HashTableClearInternal(ht);
+ if (ht != NULL) {
+ HashTableClearInternal(ht);
- free(ht->buckets);
- free(ht);
+ free(ht->buckets);
+ free(ht);
+ }
}
@@ -474,7 +470,7 @@ HashTableLookup(HashTable *ht, // IN:
Bool
HashTable_Lookup(HashTable *ht, // IN:
const void *keyStr, // IN:
- void **clientData) // OUT:
+ void **clientData) // OUT/OPT:
{
uint32 hash = HashTableComputeHash(ht, keyStr);
HashTableEntry *entry = HashTableLookup(ht, keyStr, hash);
@@ -595,7 +591,7 @@ HashTable_LookupAndDelete(HashTable *ht, // IN/OUT: the hash table
Bool
HashTable_Insert(HashTable *ht, // IN/OUT:
const void *keyStr, // IN:
- void *clientData) // IN:
+ void *clientData) // IN/OPT:
{
return HashTableLookupOrInsert(ht, keyStr, clientData) == NULL;
}
@@ -705,8 +701,8 @@ HashTable_ReplaceOrInsert(HashTable *ht, // IN/OUT:
Bool
HashTable_ReplaceIfEqual(HashTable *ht, // IN/OUT:
const void *keyStr, // IN:
- void *oldClientData, // IN:
- void *newClientData) // IN:
+ void *oldClientData, // IN/OPT:
+ void *newClientData) // IN/OPT:
{
uint32 hash = HashTableComputeHash(ht, keyStr);
HashTableEntry *entry = HashTableLookup(ht, keyStr, hash);
@@ -760,7 +756,7 @@ HashTable_ReplaceIfEqual(HashTable *ht, // IN/OUT:
HashTableEntry *
HashTableLookupOrInsert(HashTable *ht, // IN/OUT:
const void *keyStr, // IN:
- void *clientData) // IN:
+ void *clientData) // IN/OPT:
{
uint32 hash = HashTableComputeHash(ht, keyStr);
HashTableEntry *entry = NULL;
diff --git a/open-vm-tools/lib/misc/hostType.c b/open-vm-tools/lib/misc/hostType.c
index 557075de..dd9bf817 100644
--- a/open-vm-tools/lib/misc/hostType.c
+++ b/open-vm-tools/lib/misc/hostType.c
@@ -19,49 +19,44 @@
/*
* hostType.c --
*
- * Platform-independent code that calls into hostType<OS>-specific
- * code to determine the host OS type.
+ * Platform-independent code that determines the host OS type.
*/
-#include <stdlib.h>
#include <string.h>
+#ifdef __linux__
+#include <sys/utsname.h>
+#include <unistd.h>
+#endif
#include "vmware.h"
#include "hostType.h"
-#include "str.h"
-
-/*
- * XXX see bug 651592 for how to make this not warn on newer linux hosts
- * that have deprecated sysctl.
- */
-#if defined(VMX86_SERVER) || ((defined(VMX86_VPX) || defined(VMX86_VMACORE)) && defined(linux))
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <unistd.h>
-#include "uwvmkAPI.h"
-#define DO_REAL_HOST_CHECK
-#endif
-#define LGPFX "HOSTTYPE:"
/*
*----------------------------------------------------------------------
*
- * HostTypeOSVMKernelType --
+ * HostType_OSIsVMK --
*
- * Are we running on a flavor of VMKernel? Only if the KERN_OSTYPE
- * sysctl returns one of USERWORLD_SYSCTL_KERN_OSTYPE,
- * USERWORLD_SYSCTL_VISOR_OSTYPE or USERWORLD_SYSCTL_VISOR64_OSTYPE
+ * Are we running on a flavor of VMKernel?
*
- * Results:
- * 4 if running in a VMvisor UserWorld on the 64-bit vmkernel in ESX.
- * 3 if running directly in a UserWorld on the 64-bit vmkernel** in ESX.
- * 2 if running in a VMvisor UserWorld on the vmkernel in ESX.
- * 1 if running directly in a UserWorld on the vmkernel in ESX.
- * 0 if running on the COS or in a non-server product.
+ * Per bug 651592 comment #3 and elsewhere:
+ * - all ESX/ESXi compilation defines __linux__ because vmkernel
+ * implements the int80 Linux syscall family.
+ * - ESXi 5.0 and later set utsname.sysname to "VMkernel".
+ * - ESXi 3.5, 4.0, and 4.1 have unverified behavior.
+ * - ESX Classic through 4.x set utsname.sysname to "Linux".
+ * This implementation of the code assumes Classic mode does not
+ * exist and ESXi is at least version 5, which covers all versions
+ * currently supported by this codebase and happens to be a much
+ * simpler matrix.
*
- * **Note that 64-bit vmkernel in ESX does not currently exist.
+ * Should it ever become necessary to revive the check for Classic,
+ * checking for the existence of "/usr/lib/vmware/vmkernel" would
+ * suffice.
+ *
+ * Results:
+ * TRUE if running in a UserWorld on the vmkernel in ESX.
+ * FALSE if running in a non-ESX product.
*
* Side effects:
* None.
@@ -69,58 +64,39 @@
*----------------------------------------------------------------------
*/
-static int
-HostTypeOSVMKernelType(void)
+Bool
+HostType_OSIsVMK(void)
{
-#ifdef DO_REAL_HOST_CHECK
- static int vmkernelType = -1;
-
- if (vmkernelType == -1) {
- char osname[128];
- size_t osnameLength;
- int kernOsTypeCtl[] = { CTL_KERN, KERN_OSTYPE };
+#if defined __linux__
+ /*
+ * Implementation note: it might make sense to short-circuit this whole
+ * clause with "if (vmx86_server)" so that non-ESX builds get an even
+ * cheaper test. I have chosen not to do so: some non-ESX code (e.g. fdm)
+ * needs this check to act properly under a VMX86_VPX conditional. Saving
+ * a couple of cycles is not worth the effort of maintaining a product-
+ * specific macro in multi-product library code.
+ */
+ static enum {
+ VMKTYPE_UNKNOWN = 0, // to make default in .bss
+ VMKTYPE_LINUX,
+ VMKTYPE_VMKERNEL,
+ } vmkernelType = VMKTYPE_UNKNOWN;
+
+ if (vmkernelType == VMKTYPE_UNKNOWN) {
+ struct utsname name;
int rc;
-
- osnameLength = sizeof(osname);
- rc = sysctl(kernOsTypeCtl, ARRAYSIZE(kernOsTypeCtl),
- osname, &osnameLength,
- 0, 0);
- if (rc == 0) {
- osnameLength = MAX(sizeof (osname), osnameLength);
- /*
- * XXX Yes, this is backwards in order of probability now, but we
- * call it only once and anyway someday it won't be backwards ...
- */
-
- if (! strncmp(osname, USERWORLD_SYSCTL_VISOR64_OSTYPE,
- osnameLength)) {
- vmkernelType = 4;
- } else if (! strncmp(osname, USERWORLD_SYSCTL_KERN64_OSTYPE,
- osnameLength)) {
- vmkernelType = 3;
- } else if (! strncmp(osname, USERWORLD_SYSCTL_VISOR_OSTYPE,
- osnameLength)) {
- vmkernelType = 2;
- } else if (! strncmp(osname, USERWORLD_SYSCTL_KERN_OSTYPE,
- osnameLength)) {
- vmkernelType = 1;
- } else {
- vmkernelType = 0;
- }
+ rc = uname(&name);
+ if (rc == 0 && strcmp("VMkernel", name.sysname) == 0) {
+ vmkernelType = VMKTYPE_VMKERNEL;
} else {
- /*
- * XXX too many of the callers don't define Warning. See bug 125455
- */
-
- vmkernelType = 0;
+ vmkernelType = VMKTYPE_LINUX;
}
}
-
- return (vmkernelType);
+ return vmkernelType == VMKTYPE_VMKERNEL;
#else
/* Non-linux builds are never running in a userworld */
- return 0;
+ return FALSE;
#endif
}
@@ -128,85 +104,6 @@ HostTypeOSVMKernelType(void)
/*
*----------------------------------------------------------------------
*
- * HostType_OSIsVMK --
- *
- * Are we running on the VMKernel (_any_ varient)? True if KERN_OSTYPE
- * sysctl returns _any_ of
- *
- * "UserWorld/VMKernel"
- * "VMKernel"
- * "UserWorld/VMKernel64"
- * "VMKernel64"
- *
- * Results:
- * TRUE if running in a UserWorld on the vmkernel in ESX.
- * FALSE if running on the COS or in a non-server product.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-HostType_OSIsVMK(void)
-{
- return (HostTypeOSVMKernelType() > 0);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * HostType_OSIsPureVMK --
- *
- * Are we running on the VMvisor VMKernel (_any_ bitness)? True if
- * KERN_OSTYPE sysctl returns "VMKernel" or "VMKernel64".
- *
- * Results:
- * TRUE if running in a VMvisor UserWorld on the vmkernel in ESX.
- * FALSE if running on any other type of ESX or in a non-server product.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-HostType_OSIsPureVMK(void)
-{
- return (HostTypeOSVMKernelType() == 2 || HostTypeOSVMKernelType() == 4);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * HostType_OSIsVMK64 --
- *
- * Are we running on a 64-bit VMKernel? Only if the KERN_OSTYPE
- * sysctl returns "UserWorld/VMKernel64" or "VMKernel64".
- *
- * Results:
- * TRUE if running in a UserWorld on a 64-bit vmkernel in ESX or VMvisor.
- * FALSE if running on a 32-bit VMkernel in ESX or in a non-server product.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-HostType_OSIsVMK64(void)
-{
- return (HostTypeOSVMKernelType() == 3 || HostTypeOSVMKernelType() == 4);
-}
-
-/*
- *----------------------------------------------------------------------
- *
* HostType_OSIsSimulator --
*
* Are we running on an ESX host simulator? Check presence of the
@@ -225,7 +122,7 @@ HostType_OSIsVMK64(void)
Bool
HostType_OSIsSimulator(void)
{
-#ifdef DO_REAL_HOST_CHECK
+#if defined __linux__ && (defined VMX86_SERVER || defined VMX86_VPX || defined VMX86_VMACORE)
static int simulatorType = -1;
if (simulatorType == -1) {
if (access("/etc/vmware/hostd/mockupEsxHost.txt", 0) != -1) {
diff --git a/open-vm-tools/lib/misc/hostinfoPosix.c b/open-vm-tools/lib/misc/hostinfoPosix.c
index 6c13fe3b..a9e7d6cb 100644
--- a/open-vm-tools/lib/misc/hostinfoPosix.c
+++ b/open-vm-tools/lib/misc/hostinfoPosix.c
@@ -75,7 +75,11 @@
#include <sys/vfs.h>
#endif
#if !defined(sun) && !defined __ANDROID__ && (!defined(USING_AUTOCONF) || (defined(HAVE_SYS_IO_H) && defined(HAVE_SYS_SYSINFO_H)))
+#if defined(__i386__) || defined(__x86_64__)
#include <sys/io.h>
+#else
+#define NO_IOPL
+#endif
#include <sys/sysinfo.h>
#ifndef HAVE_SYSINFO
#define HAVE_SYSINFO 1
@@ -151,12 +155,12 @@ static Atomic_Ptr hostinfoOSVersion;
#define DISTRO_BUF_SIZE 255
+#if !defined __APPLE__ && !defined USERWORLD
typedef struct lsb_distro_info {
char *name;
char *scanstring;
} LSBDistroInfo;
-
static const LSBDistroInfo lsbFields[] = {
{"DISTRIB_ID=", "DISTRIB_ID=%s"},
{"DISTRIB_RELEASE=", "DISTRIB_RELEASE=%s"},
@@ -165,30 +169,13 @@ static const LSBDistroInfo lsbFields[] = {
{NULL, NULL},
};
-
typedef struct distro_info {
char *name;
char *filename;
} DistroInfo;
+/* KEEP SORTED! (sort -d) */
static const DistroInfo distroArray[] = {
- {"OracleLinux", "/etc/oracle-release"},
- {"RedHat", "/etc/redhat-release"},
- {"RedHat", "/etc/redhat_version"},
- {"Sun", "/etc/sun-release"},
- {"SuSE", "/etc/SuSE-release"},
- {"SuSE", "/etc/novell-release"},
- {"SuSE", "/etc/sles-release"},
- {"Debian", "/etc/debian_version"},
- {"Debian", "/etc/debian_release"},
- {"Mandrake", "/etc/mandrake-release"},
- {"Mandriva", "/etc/mandriva-release"},
- {"Mandrake", "/etc/mandrakelinux-release"},
- {"TurboLinux", "/etc/turbolinux-release"},
- {"Fedora Core", "/etc/fedora-release"},
- {"Gentoo", "/etc/gentoo-release"},
- {"Novell", "/etc/nld-release"},
- {"Ubuntu", "/etc/lsb-release"},
{"Annvix", "/etc/annvix-release"},
{"Arch", "/etc/arch-release"},
{"Arklinux", "/etc/arklinux-release"},
@@ -196,23 +183,42 @@ static const DistroInfo distroArray[] = {
{"BlackCat", "/etc/blackcat-release"},
{"Cobalt", "/etc/cobalt-release"},
{"Conectiva", "/etc/conectiva-release"},
+ {"Debian", "/etc/debian_release"},
+ {"Debian", "/etc/debian_version"},
+ {"Fedora Core", "/etc/fedora-release"},
+ {"Gentoo", "/etc/gentoo-release"},
{"Immunix", "/etc/immunix-release"},
{"Knoppix", "/etc/knoppix_version"},
{"Linux-From-Scratch", "/etc/lfs-release"},
{"Linux-PPC", "/etc/linuxppc-release"},
+ {"Mandrake", "/etc/mandrakelinux-release"},
+ {"Mandrake", "/etc/mandrake-release"},
+ {"Mandriva", "/etc/mandriva-release"},
{"MkLinux", "/etc/mklinux-release"},
+ {"Novell", "/etc/nld-release"},
+ {"OracleLinux", "/etc/oracle-release"},
+ {"Photon", "/etc/lsb-release"},
{"PLD", "/etc/pld-release"},
- {"Slackware", "/etc/slackware-version"},
+ {"RedHat", "/etc/redhat-release"},
+ {"RedHat", "/etc/redhat_version"},
{"Slackware", "/etc/slackware-release"},
+ {"Slackware", "/etc/slackware-version"},
{"SMEServer", "/etc/e-smith-release"},
{"Solaris", "/etc/release"},
+ {"Sun", "/etc/sun-release"},
+ {"SuSE", "/etc/novell-release"},
+ {"SuSE", "/etc/sles-release"},
+ {"SuSE", "/etc/SuSE-release"},
{"Tiny Sofa", "/etc/tinysofa-release"},
+ {"TurboLinux", "/etc/turbolinux-release"},
+ {"Ubuntu", "/etc/lsb-release"},
{"UltraPenguin", "/etc/ultrapenguin-release"},
{"UnitedLinux", "/etc/UnitedLinux-release"},
{"VALinux", "/etc/va-release"},
{"Yellow Dog", "/etc/yellowdog-release"},
{NULL, NULL},
};
+#endif
#if defined __ANDROID__
/*
@@ -1394,24 +1400,24 @@ Hostinfo_OSIsSMP(void)
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
Hostinfo_NameGet(void)
{
- Unicode result;
+ char *result;
static Atomic_Ptr state; /* Implicitly initialized to NULL. --hpreg */
result = Atomic_ReadPtr(&state);
if (UNLIKELY(result == NULL)) {
- Unicode before;
+ char *before;
result = Hostinfo_HostName();
before = Atomic_ReadIfEqualWritePtr(&state, NULL, result);
if (before) {
- Unicode_Free(result);
+ free(result);
result = before;
}
@@ -1438,14 +1444,14 @@ Hostinfo_NameGet(void)
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
Hostinfo_GetUser(void)
{
char buffer[BUFSIZ];
struct passwd pw;
struct passwd *ppw = &pw;
- Unicode env = NULL;
- Unicode name = NULL;
+ char *env = NULL;
+ char *name = NULL;
if ((Posix_Getpwuid_r(getuid(), &pw, buffer, sizeof buffer, &ppw) == 0) &&
(ppw != NULL)) {
@@ -1816,7 +1822,7 @@ HostinfoSystemTimerPosix(VmTimeType *result) // OUT
VmTimeType
Hostinfo_SystemTimerNS(void)
{
- VmTimeType result;
+ VmTimeType result = 0; // = 0 silence compiler warning
if ((vmx86_apple && HostinfoSystemTimerMach(&result)) ||
(vmx86_posix && HostinfoSystemTimerPosix(&result))) {
@@ -2610,6 +2616,9 @@ Hostinfo_GetCpuDescription(uint32 cpuNumber) // IN:
return HostinfoGetSysctlStringAlloc("hw.model");
#else
#ifdef VMX86_SERVER
+#ifdef VM_ARM_64
+ return strdup("armv8 unknown");
+#else
if (HostType_OSIsVMK()) {
char mName[48];
@@ -2624,7 +2633,8 @@ Hostinfo_GetCpuDescription(uint32 cpuNumber) // IN:
return NULL;
}
-#endif
+#endif // VM_ARM_64
+#endif // VMX86_SERVER
return HostinfoGetCpuInfo(cpuNumber, "model name");
#endif
@@ -3020,7 +3030,7 @@ Hostinfo_SystemUpTime(void)
* /proc/uptime does not exist on Visor. Use syscall instead.
* Discovering Visor is a run-time check with a compile-time hint.
*/
- if (vmx86_server && HostType_OSIsPureVMK()) {
+ if (vmx86_server && HostType_OSIsVMK()) {
uint64 uptime;
#ifdef VMX86_SERVER
if (UNLIKELY(VMKernel_GetUptimeUS(&uptime) != VMK_OK)) {
@@ -3508,10 +3518,10 @@ Hostinfo_GetMemoryInfoInPages(unsigned int *minSize, // OUT:
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
Hostinfo_GetModulePath(uint32 priv) // IN:
{
- Unicode path;
+ char *path;
#if defined(__APPLE__)
uint32_t pathSize = FILE_MAXPATH;
diff --git a/open-vm-tools/lib/misc/hostname.c b/open-vm-tools/lib/misc/hostname.c
index 5bfcfc99..06b20769 100644
--- a/open-vm-tools/lib/misc/hostname.c
+++ b/open-vm-tools/lib/misc/hostname.c
@@ -60,10 +60,10 @@
*----------------------------------------------------------------------
*/
-Unicode
+char *
Hostinfo_HostName(void)
{
- Unicode result;
+ char *result;
HMODULE dllHandle;
struct hostent *myHostEnt;
struct hostent *(WINAPI *GetHostByNameFn)(char *hostName);
@@ -156,12 +156,12 @@ Hostinfo_HostName(void)
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
Hostinfo_HostName(void)
{
struct utsname un;
- Unicode result = NULL;
+ char *result = NULL;
if ((uname(&un) == 0) && (*un.nodename != '\0')) {
/* 'un.nodename' is already fully qualified. */
@@ -192,12 +192,12 @@ Hostinfo_HostName(void)
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
Hostinfo_HostName(void)
{
struct utsname un;
- Unicode result = NULL;
+ char *result = NULL;
if ((uname(&un) == 0) && (*un.nodename != '\0')) {
char *p;
@@ -242,7 +242,7 @@ Hostinfo_HostName(void)
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
Hostinfo_HostName(void)
{
return NULL;
diff --git a/open-vm-tools/lib/misc/idLinux.c b/open-vm-tools/lib/misc/idLinux.c
index 9e40cb7f..58bcb532 100644
--- a/open-vm-tools/lib/misc/idLinux.c
+++ b/open-vm-tools/lib/misc/idLinux.c
@@ -59,7 +59,7 @@
* And obviously, we're not using glibc 2.0
* for our 64bit builds!
*/
-#ifdef VM_X86_64
+#ifdef VM_64BIT
#define SYS_setreuid32 (abort(), 0)
#define SYS_setregid32 (abort(), 0)
#define SYS_setresuid32 (abort(), 0)
@@ -81,7 +81,7 @@
* with the '32' suffix, so we get the behaviour we want by forcing
* the code to use the unsuffixed syscalls.
*/
-#ifdef VM_X86_64
+#ifdef VM_64BIT
static int uid32 = 0;
#else
static int uid32 = 1;
diff --git a/open-vm-tools/lib/misc/iovector.c b/open-vm-tools/lib/misc/iovector.c
index eaec35fe..54f083a7 100644
--- a/open-vm-tools/lib/misc/iovector.c
+++ b/open-vm-tools/lib/misc/iovector.c
@@ -460,7 +460,7 @@ IOV_Split(VMIOVec *origV, // IN/OUT: VMIOVec for whole xfer
*
* This function takes an iov and a buffer as input and writes the content
* of the buffers pointed to by the iov into buf.
- *
+ *
* Result:
* None.
*
@@ -471,10 +471,10 @@ IOV_Split(VMIOVec *origV, // IN/OUT: VMIOVec for whole xfer
*/
void
-IOV_WriteIovToBuf(struct iovec* entries, // IN
- int numEntries, // IN
- uint8* bufOut, // OUT
- size_t bufSize) // IN
+IOV_WriteIovToBuf(struct iovec const *entries, // IN
+ int numEntries, // IN
+ uint8 *bufOut, // OUT
+ size_t bufSize) // IN
{
size_t count = 0;
int i;
@@ -570,7 +570,7 @@ IOV_Free(VMIOVec* iov) // IN
*
* This function copies the content of bufIn into the buffer pointed to by
* entries. It basically does the opposite of IOV_WriteIovToBuf.
- *
+ *
* Result:
* None.
*
@@ -581,10 +581,10 @@ IOV_Free(VMIOVec* iov) // IN
*/
void
-IOV_WriteBufToIov(const uint8* bufIn, // IN
- size_t bufSize, // IN
- struct iovec* entries, // OUT
- int numEntries) // IN
+IOV_WriteBufToIov(const uint8 *bufIn, // IN
+ size_t bufSize, // IN
+ struct iovec const *entries, // OUT
+ int numEntries) // IN
{
size_t count = 0;
int i;
diff --git a/open-vm-tools/lib/misc/msgList.c b/open-vm-tools/lib/misc/msgList.c
index efd582fa..0b6d01ea 100644
--- a/open-vm-tools/lib/misc/msgList.c
+++ b/open-vm-tools/lib/misc/msgList.c
@@ -194,9 +194,9 @@ MsgList_AppendStr(MsgList **list, // IN reference to existing list
*/
void
-MsgList_VAppend(MsgList **list, // IN reference to existing list
- const char *idFmt, // IN message ID and English message
- va_list args) // IN args
+MsgList_VAppend(MsgList **list, // IN/OUT/OPT: reference to existing list
+ const char *idFmt, // IN: message ID and English message
+ va_list args) // IN: args
{
ASSERT(idFmt != NULL);
@@ -251,9 +251,9 @@ MsgList_VAppend(MsgList **list, // IN reference to existing list
*/
void
-MsgList_Append(MsgList **list, // IN reference to existing list
- const char *idFmt, // IN message ID and English message
- ...) // IN args
+MsgList_Append(MsgList **list, // IN/OUT/OPT: reference to existing list
+ const char *idFmt, // IN: message ID and English message
+ ...) // IN: args
{
va_list args;
diff --git a/open-vm-tools/lib/misc/posixDlopen.c b/open-vm-tools/lib/misc/posixDlopen.c
index a82cd1a2..3d40938c 100644
--- a/open-vm-tools/lib/misc/posixDlopen.c
+++ b/open-vm-tools/lib/misc/posixDlopen.c
@@ -48,8 +48,8 @@
*/
void *
-Posix_Dlopen(ConstUnicode pathName, // IN:
- int flag) // IN:
+Posix_Dlopen(const char *pathName, // IN:
+ int flag) // IN:
{
char *path;
void *ret;
diff --git a/open-vm-tools/lib/misc/posixInt.h b/open-vm-tools/lib/misc/posixInt.h
index 8e41ca65..598a02ff 100644
--- a/open-vm-tools/lib/misc/posixInt.h
+++ b/open-vm-tools/lib/misc/posixInt.h
@@ -43,8 +43,7 @@
*
* PosixConvertToCurrent --
*
- * Utility function to convert a Unicode string
- * to the current encoding.
+ * Utility function to convert a UTF8 string to the current encoding.
*
* Results:
* TRUE on success.
@@ -59,8 +58,8 @@
*/
static INLINE Bool
-PosixConvertToCurrent(ConstUnicode in, // IN: string to convert
- char **out) // OUT: conversion result
+PosixConvertToCurrent(const char *in, // IN: string to convert
+ char **out) // OUT: conversion result
{
int e = errno;
char *p = Unicode_GetAllocBytes(in, STRING_ENCODING_DEFAULT);
@@ -82,9 +81,8 @@ PosixConvertToCurrent(ConstUnicode in, // IN: string to convert
*
* PosixConvertToCurrentList --
*
- * Utility function to convert a list of Unicode strings
- * to the current encoding.
- * Return NULL if list is NULL.
+ * Utility function to convert a list of UTF8 strings to the current
+ * encoding. Return NULL if list is NULL.
*
* Results:
* TRUE on success.
@@ -99,8 +97,8 @@ PosixConvertToCurrent(ConstUnicode in, // IN: string to convert
*/
static INLINE Bool
-PosixConvertToCurrentList(Unicode const *in, // IN: list to convert
- char ***out) // OUT: conversion result
+PosixConvertToCurrentList(char *const *in, // IN: list to convert
+ char ***out) // OUT: conversion result
{
int e = errno;
char **p;
@@ -147,8 +145,7 @@ PosixEnvFree(void *v)
*
* PosixGetenvHash --
*
- * Save away Unicode result for Posix_Getenv() to make
- * it persistent.
+ * Save away UTF8 string for Posix_Getenv() to make it persistent.
*
* Results:
* The value.
@@ -160,13 +157,13 @@ PosixEnvFree(void *v)
*-----------------------------------------------------------------------------
*/
-static INLINE_SINGLE_CALLER Unicode
-PosixGetenvHash(ConstUnicode name, // IN
- Unicode value) // IN/OUT: may be freed
+static INLINE_SINGLE_CALLER char *
+PosixGetenvHash(const char *name, // IN
+ char *value) // IN/OUT: may be freed
{
static Atomic_Ptr htPtr;
HashTable *ht;
- Unicode oldValue;
+ char *oldValue;
PosixEnvEntry *e;
/*
@@ -214,7 +211,7 @@ PosixGetenvHash(ConstUnicode name, // IN
oldValue = Atomic_ReadPtr(&e->value);
if (Str_Strcmp(oldValue, value) == 0) {
- Unicode_Free(value);
+ free(value);
value = oldValue;
break;
}
@@ -229,7 +226,7 @@ PosixGetenvHash(ConstUnicode name, // IN
if (Atomic_ReadIfEqualWritePtr(&e->value, oldValue, value) == oldValue) {
oldValue = Atomic_ReadWritePtr(&e->lastValue, oldValue);
- Unicode_Free(oldValue);
+ free(oldValue);
break;
}
}
diff --git a/open-vm-tools/lib/misc/posixPosix.c b/open-vm-tools/lib/misc/posixPosix.c
index 68b0a76d..c0546e63 100644
--- a/open-vm-tools/lib/misc/posixPosix.c
+++ b/open-vm-tools/lib/misc/posixPosix.c
@@ -108,9 +108,9 @@ EXTERN int truncate(const char *, off_t);
*/
int
-Posix_Open(ConstUnicode pathName, // IN:
- int flags, // IN:
- ...) // IN:
+Posix_Open(const char *pathName, // IN:
+ int flags, // IN:
+ ...) // IN:
{
char *path;
mode_t mode = 0;
@@ -162,8 +162,8 @@ Posix_Open(ConstUnicode pathName, // IN:
*/
int
-Posix_Creat(ConstUnicode pathName, // IN:
- mode_t mode) // IN:
+Posix_Creat(const char *pathName, // IN:
+ mode_t mode) // IN:
{
return Posix_Open(pathName, O_CREAT | O_WRONLY | O_TRUNC, mode);
}
@@ -186,8 +186,8 @@ Posix_Creat(ConstUnicode pathName, // IN:
*/
FILE *
-Posix_Fopen(ConstUnicode pathName, // IN:
- const char *mode) // IN:
+Posix_Fopen(const char *pathName, // IN:
+ const char *mode) // IN:
{
char *path;
FILE *stream;
@@ -224,8 +224,8 @@ Posix_Fopen(ConstUnicode pathName, // IN:
*/
int
-Posix_Stat(ConstUnicode pathName, // IN:
- struct stat *statbuf) // IN:
+Posix_Stat(const char *pathName, // IN:
+ struct stat *statbuf) // IN:
{
char *path;
int ret;
@@ -260,8 +260,8 @@ Posix_Stat(ConstUnicode pathName, // IN:
*/
int
-Posix_Chmod(ConstUnicode pathName, // IN:
- mode_t mode) // IN:
+Posix_Chmod(const char *pathName, // IN:
+ mode_t mode) // IN:
{
char *path;
int ret;
@@ -295,8 +295,8 @@ Posix_Chmod(ConstUnicode pathName, // IN:
*/
int
-Posix_Rename(ConstUnicode fromPathName, // IN:
- ConstUnicode toPathName) // IN:
+Posix_Rename(const char *fromPathName, // IN:
+ const char *toPathName) // IN:
{
char *toPath;
char *fromPath;
@@ -336,7 +336,7 @@ Posix_Rename(ConstUnicode fromPathName, // IN:
*/
int
-Posix_Unlink(ConstUnicode pathName) // IN:
+Posix_Unlink(const char *pathName) // IN:
{
char *path;
int ret;
@@ -370,7 +370,7 @@ Posix_Unlink(ConstUnicode pathName) // IN:
*/
int
-Posix_Rmdir(ConstUnicode pathName) // IN:
+Posix_Rmdir(const char *pathName) // IN:
{
char *path;
int ret;
@@ -405,9 +405,9 @@ Posix_Rmdir(ConstUnicode pathName) // IN:
*/
FILE *
-Posix_Freopen(ConstUnicode pathName, // IN:
- const char *mode, // IN:
- FILE *input_stream) // IN:
+Posix_Freopen(const char *pathName, // IN:
+ const char *mode, // IN:
+ FILE *input_stream) // IN:
{
char *path;
FILE *stream;
@@ -443,8 +443,8 @@ Posix_Freopen(ConstUnicode pathName, // IN:
*/
int
-Posix_Access(ConstUnicode pathName, // IN:
- int mode) // IN:
+Posix_Access(const char *pathName, // IN:
+ int mode) // IN:
{
char *path;
int ret;
@@ -491,8 +491,8 @@ Posix_Access(ConstUnicode pathName, // IN:
*/
int
-Posix_EuidAccess(ConstUnicode pathName, // IN:
- int mode) // IN:
+Posix_EuidAccess(const char *pathName, // IN:
+ int mode) // IN:
{
#if defined(GLIBC_VERSION_24)
char *path;
@@ -531,7 +531,7 @@ Posix_EuidAccess(ConstUnicode pathName, // IN:
*/
int
-Posix_Utime(ConstUnicode pathName, // IN:
+Posix_Utime(const char *pathName, // IN:
const struct utimbuf *times) // IN:
{
char *path;
@@ -567,7 +567,7 @@ Posix_Utime(ConstUnicode pathName, // IN:
*/
void
-Posix_Perror(ConstUnicode str) // IN:
+Posix_Perror(const char *str) // IN:
{
char *tmpstr = Unicode_GetAllocBytes(str, STRING_ENCODING_DEFAULT);
@@ -595,8 +595,8 @@ Posix_Perror(ConstUnicode str) // IN:
*/
long
-Posix_Pathconf(ConstUnicode pathName, // IN:
- int name) // IN:
+Posix_Pathconf(const char *pathName, // IN:
+ int name) // IN:
{
char *path;
long ret;
@@ -631,8 +631,8 @@ Posix_Pathconf(ConstUnicode pathName, // IN:
*/
FILE *
-Posix_Popen(ConstUnicode pathName, // IN:
- const char *mode) // IN:
+Posix_Popen(const char *pathName, // IN:
+ const char *mode) // IN:
{
char *path;
FILE *stream;
@@ -669,9 +669,9 @@ Posix_Popen(ConstUnicode pathName, // IN:
*/
int
-Posix_Mknod(ConstUnicode pathName, // IN:
- mode_t mode, // IN:
- dev_t dev) // IN:
+Posix_Mknod(const char *pathName, // IN:
+ mode_t mode, // IN:
+ dev_t dev) // IN:
{
char *path;
int ret;
@@ -706,9 +706,9 @@ Posix_Mknod(ConstUnicode pathName, // IN:
*/
int
-Posix_Chown(ConstUnicode pathName, // IN:
- uid_t owner, // IN:
- gid_t group) // IN:
+Posix_Chown(const char *pathName, // IN:
+ uid_t owner, // IN:
+ gid_t group) // IN:
{
char *path;
int ret;
@@ -743,9 +743,9 @@ Posix_Chown(ConstUnicode pathName, // IN:
*/
int
-Posix_Lchown(ConstUnicode pathName, // IN:
- uid_t owner, // IN:
- gid_t group) // IN:
+Posix_Lchown(const char *pathName, // IN:
+ uid_t owner, // IN:
+ gid_t group) // IN:
{
char *path;
int ret;
@@ -780,8 +780,8 @@ Posix_Lchown(ConstUnicode pathName, // IN:
*/
int
-Posix_Link(ConstUnicode pathName1, // IN:
- ConstUnicode pathName2) // IN:
+Posix_Link(const char *pathName1, // IN:
+ const char *pathName2) // IN:
{
char *path1;
char *path2;
@@ -823,8 +823,8 @@ Posix_Link(ConstUnicode pathName1, // IN:
*/
int
-Posix_Symlink(ConstUnicode pathName1, // IN:
- ConstUnicode pathName2) // IN:
+Posix_Symlink(const char *pathName1, // IN:
+ const char *pathName2) // IN:
{
char *path1;
char *path2;
@@ -866,8 +866,8 @@ Posix_Symlink(ConstUnicode pathName1, // IN:
*/
int
-Posix_Mkfifo(ConstUnicode pathName, // IN:
- mode_t mode) // IN:
+Posix_Mkfifo(const char *pathName, // IN:
+ mode_t mode) // IN:
{
char *path;
int ret;
@@ -902,8 +902,8 @@ Posix_Mkfifo(ConstUnicode pathName, // IN:
*/
int
-Posix_Truncate(ConstUnicode pathName, // IN:
- off_t length) // IN:
+Posix_Truncate(const char *pathName, // IN:
+ off_t length) // IN:
{
char *path;
int ret;
@@ -938,7 +938,7 @@ Posix_Truncate(ConstUnicode pathName, // IN:
*/
int
-Posix_Utimes(ConstUnicode pathName, // IN:
+Posix_Utimes(const char *pathName, // IN:
const struct timeval *times) // IN:
{
char *path;
@@ -974,8 +974,9 @@ Posix_Utimes(ConstUnicode pathName, // IN:
*/
int
-Posix_Execl(ConstUnicode pathName, // IN:
- ConstUnicode arg0, ...) // IN:
+Posix_Execl(const char *pathName, // IN:
+ const char *arg0, // IN:
+ ...) // IN:
{
int ret = -1;
char *path;
@@ -1052,9 +1053,9 @@ exit:
*/
int
-Posix_Execlp(ConstUnicode fileName, // IN:
- ConstUnicode arg0, // IN:
- ...) // IN:
+Posix_Execlp(const char *fileName, // IN:
+ const char *arg0, // IN:
+ ...) // IN:
{
int ret = -1;
char *file;
@@ -1131,8 +1132,8 @@ exit:
*/
int
-Posix_Execv(ConstUnicode pathName, // IN:
- Unicode const argVal[]) // IN:
+Posix_Execv(const char *pathName, // IN:
+ char *const argVal[]) // IN:
{
int ret = -1;
char *path;
@@ -1175,9 +1176,9 @@ exit:
*/
int
-Posix_Execve(ConstUnicode pathName, // IN:
- Unicode const argVal[], // IN:
- Unicode const envPtr[]) // IN:
+Posix_Execve(const char *pathName, // IN:
+ char *const argVal[], // IN:
+ char *const envPtr[]) // IN:
{
int ret = -1;
char *path;
@@ -1227,8 +1228,8 @@ exit:
*/
int
-Posix_Execvp(ConstUnicode fileName, // IN:
- Unicode const argVal[]) // IN:
+Posix_Execvp(const char *fileName, // IN:
+ char *const argVal[]) // IN:
{
int ret = -1;
char *file;
@@ -1270,7 +1271,7 @@ exit:
*/
int
-Posix_System(ConstUnicode command) // IN:
+Posix_System(const char *command) // IN:
{
char *tmpcommand;
int ret;
@@ -1305,8 +1306,8 @@ Posix_System(ConstUnicode command) // IN:
*/
int
-Posix_Mkdir(ConstUnicode pathName, // IN:
- mode_t mode) // IN:
+Posix_Mkdir(const char *pathName, // IN:
+ mode_t mode) // IN:
{
char *path;
int ret;
@@ -1341,7 +1342,7 @@ Posix_Mkdir(ConstUnicode pathName, // IN:
*/
int
-Posix_Chdir(ConstUnicode pathName) // IN:
+Posix_Chdir(const char *pathName) // IN:
{
char *path;
int ret;
@@ -1375,8 +1376,8 @@ Posix_Chdir(ConstUnicode pathName) // IN:
*----------------------------------------------------------------------
*/
-Unicode
-Posix_RealPath(ConstUnicode pathName) // IN:
+char *
+Posix_RealPath(const char *pathName) // IN:
{
char *path;
char rpath[PATH_MAX];
@@ -1411,11 +1412,11 @@ Posix_RealPath(ConstUnicode pathName) // IN:
*----------------------------------------------------------------------
*/
-Unicode
-Posix_ReadLink(ConstUnicode pathName) // IN:
+char *
+Posix_ReadLink(const char *pathName) // IN:
{
char *path = NULL;
- Unicode result = NULL;
+ char *result = NULL;
if (PosixConvertToCurrent(pathName, &path)) {
size_t size = 2 * 1024;
@@ -1465,8 +1466,8 @@ Posix_ReadLink(ConstUnicode pathName) // IN:
*/
int
-Posix_Lstat(ConstUnicode pathName, // IN:
- struct stat *statbuf) // IN:
+Posix_Lstat(const char *pathName, // IN:
+ struct stat *statbuf) // IN:
{
char *path;
int ret;
@@ -1501,7 +1502,7 @@ Posix_Lstat(ConstUnicode pathName, // IN:
*/
DIR *
-Posix_OpenDir(ConstUnicode pathName) // IN:
+Posix_OpenDir(const char *pathName) // IN:
{
char *path;
DIR *ret;
@@ -1536,8 +1537,8 @@ Posix_OpenDir(ConstUnicode pathName) // IN:
*----------------------------------------------------------------------
*/
-Unicode
-Posix_Getenv(ConstUnicode name) // IN:
+char *
+Posix_Getenv(const char *name) // IN:
{
char *rawName;
char *rawValue;
@@ -1576,7 +1577,7 @@ Posix_Getenv(ConstUnicode name) // IN:
*/
int
-Posix_Putenv(Unicode name) // IN:
+Posix_Putenv(char *name) // IN:
{
ASSERT(Unicode_IsBufferValid(name, -1, STRING_ENCODING_US_ASCII));
@@ -1604,7 +1605,7 @@ Posix_Putenv(Unicode name) // IN:
*/
int
-Posix_Statfs(ConstUnicode pathName, // IN:
+Posix_Statfs(const char *pathName, // IN:
struct statfs *statfsbuf) // IN:
{
char *path;
@@ -1641,9 +1642,9 @@ Posix_Statfs(ConstUnicode pathName, // IN:
*/
int
-Posix_Setenv(ConstUnicode name, // IN:
- ConstUnicode value, // IN:
- int overWrite) // IN:
+Posix_Setenv(const char *name, // IN:
+ const char *value, // IN:
+ int overWrite) // IN:
{
int ret = -1;
char *rawName = NULL;
@@ -1726,7 +1727,7 @@ exit:
*/
void
-Posix_Unsetenv(ConstUnicode name) // IN:
+Posix_Unsetenv(const char *name) // IN:
{
char *rawName;
@@ -1764,8 +1765,8 @@ Posix_Unsetenv(ConstUnicode name) // IN:
*/
int
-Posix_Mount(ConstUnicode source, // IN:
- ConstUnicode target, // IN:
+Posix_Mount(const char *source, // IN:
+ const char *target, // IN:
const char *filesystemtype, // IN:
unsigned long mountflags, // IN:
const void *data) // IN:
@@ -1809,7 +1810,7 @@ exit:
*/
int
-Posix_Umount(ConstUnicode target) // IN:
+Posix_Umount(const char *target) // IN:
{
char *tmptarget;
int ret;
@@ -1844,8 +1845,8 @@ Posix_Umount(ConstUnicode target) // IN:
*/
FILE *
-Posix_Setmntent(ConstUnicode pathName, // IN:
- const char *mode) // IN:
+Posix_Setmntent(const char *pathName, // IN:
+ const char *mode) // IN:
{
#if defined NO_SETMNTENT
NOT_IMPLEMENTED();
@@ -2090,11 +2091,11 @@ exit:
*/
int
-Posix_Printf(ConstUnicode format, // IN:
- ...) // IN:
+Posix_Printf(const char *format, // IN:
+ ...) // IN:
{
va_list args;
- Unicode output;
+ char *output;
char *outCurr;
int numChars;
@@ -2132,12 +2133,12 @@ Posix_Printf(ConstUnicode format, // IN:
*/
int
-Posix_Fprintf(FILE *stream, // IN:
- ConstUnicode format, // IN:
- ...) // IN:
+Posix_Fprintf(FILE *stream, // IN:
+ const char *format, // IN:
+ ...) // IN:
{
va_list args;
- Unicode output;
+ char *output;
char *outCurr;
int nOutput;
@@ -2230,10 +2231,10 @@ Posix_Getmntent(FILE *fp, // IN:
*----------------------------------------------------------------------
*/
-Unicode
-Posix_MkTemp(ConstUnicode pathName) // IN:
+char *
+Posix_MkTemp(const char *pathName) // IN:
{
- Unicode result = NULL;
+ char *result = NULL;
char *path;
int fd;
diff --git a/open-vm-tools/lib/misc/posixPwd.c b/open-vm-tools/lib/misc/posixPwd.c
index 2a9901dd..cd5ae295 100644
--- a/open-vm-tools/lib/misc/posixPwd.c
+++ b/open-vm-tools/lib/misc/posixPwd.c
@@ -63,7 +63,7 @@ static int GetpwInternal_r(struct passwd *pw, char *buf, size_t size,
*/
struct passwd *
-Posix_Getpwnam(ConstUnicode name) // IN:
+Posix_Getpwnam(const char *name) // IN:
{
struct passwd *pw;
char *tmpname;
@@ -616,7 +616,7 @@ EmulateGetgrnam_r(const char *name, // IN:
*/
int
-Posix_Getpwnam_r(ConstUnicode name, // IN:
+Posix_Getpwnam_r(const char *name, // IN:
struct passwd *pw, // IN:
char *buf, // IN:
size_t size, // IN:
@@ -858,10 +858,10 @@ exit:
*/
int
-Posix_GetGroupList(ConstUnicode user, // IN:
- gid_t group, // IN:
- gid_t *groups, // OUT:
- int *ngroups) // IN/OUT:
+Posix_GetGroupList(const char *user, // IN:
+ gid_t group, // IN:
+ gid_t *groups, // OUT:
+ int *ngroups) // IN/OUT:
{
char *tmpuser;
int ret;
@@ -917,7 +917,7 @@ Posix_GetGroupList(ConstUnicode user, // IN:
*/
struct group *
-Posix_Getgrnam(ConstUnicode name) // IN:
+Posix_Getgrnam(const char *name) // IN:
{
struct group *gr;
char *tmpname;
@@ -940,7 +940,7 @@ Posix_Getgrnam(ConstUnicode name) // IN:
free(sgr.gr_passwd);
sgr.gr_passwd = NULL;
if (sgr.gr_mem != NULL) {
- Unicode_FreeList(sgr.gr_mem, -1);
+ Util_FreeStringList(sgr.gr_mem, -1);
sgr.gr_mem = NULL;
}
@@ -993,7 +993,7 @@ Posix_Getgrnam(ConstUnicode name) // IN:
*/
int
-Posix_Getgrnam_r(ConstUnicode name, // IN:
+Posix_Getgrnam_r(const char *name, // IN:
struct group *gr, // IN:
char *buf, // IN:
size_t size, // IN:
@@ -1101,7 +1101,7 @@ Posix_Getgrnam_r(ConstUnicode name, // IN:
free(grpasswd);
free(grname);
if (grmem) {
- Unicode_FreeList(grmem, -1);
+ Util_FreeStringList(grmem, -1);
}
return ret;
diff --git a/open-vm-tools/lib/misc/random.c b/open-vm-tools/lib/misc/random.c
index 81100d27..da06f213 100644
--- a/open-vm-tools/lib/misc/random.c
+++ b/open-vm-tools/lib/misc/random.c
@@ -234,7 +234,8 @@ struct rqContext {
rqContext *
Random_QuickSeed(uint32 seed) // IN:
{
- struct rqContext *rs;
+ uint32 i;
+ struct rqContext *rs = Util_SafeMalloc(sizeof *rs);
const uint32 xx[N] = {
0x95F24DAB, 0x0B685215, 0xE76CCAE7, 0xAF3EC239, 0x715FAD23,
@@ -244,19 +245,14 @@ Random_QuickSeed(uint32 seed) // IN:
0x512C0C03, 0xEA857CCD, 0x4CC1D30F, 0x8891A8A1, 0xA6B7AADB
};
- rs = (struct rqContext *) Util_SafeMalloc(sizeof *rs);
- if (rs != NULL) {
- uint32 i;
-
- for (i = 0; i < N; i++) {
- rs->x[i] = xx[i] ^ seed;
- }
-
- rs->p = N - 1;
- rs->q = N - M - 1;
+ for (i = 0; i < N; i++) {
+ rs->x[i] = xx[i] ^ seed;
}
+ rs->p = N - 1;
+ rs->q = N - M - 1;
+
return rs;
}
diff --git a/open-vm-tools/lib/misc/sha1.c b/open-vm-tools/lib/misc/sha1.c
index ee49978f..42e16a07 100644
--- a/open-vm-tools/lib/misc/sha1.c
+++ b/open-vm-tools/lib/misc/sha1.c
@@ -31,21 +31,26 @@
*********************************************************/
/*
-SHA-1 in C
-Originally released by Steve Reid <steve@edmweb.com> into the public domain
-
-Test Vectors (from FIPS PUB 180-1)
-"abc"
- A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
- 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-/*
- 12/15/98: JEB: Removed main and moved prototypes to sha1.h
- Made SHA1Transform a static function
+ * SHA-1 in C
+ * Originally released by Steve Reid <steve@edmweb.com> into the public domain
+ *
+ * Test Vectors (from FIPS PUB 180-1)
+ * "abc"
+ * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+ * A million repetitions of "a"
+ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+ *
+ * Major changes:
+ *
+ * 12/98: JEB: Removed main and moved prototypes to sha1.h
+ * Made SHA1Transform a static function
+ *
+ * 10/14: rberinde: Added SSE3 code and test, cleaned up a bit.
+ *
+ * If any changes are made to this file, please run:
+ * test-esx -n misc/sha1.sh
*/
#if defined(USERLEVEL) || defined(_WIN32)
@@ -84,6 +89,93 @@ A million repetitions of "a"
#include "vm_basic_asm.h"
#include "vmk_exports.h"
+
+/*
+ * The SSSE3 implementation is only 64-bit and it is excluded from monitor,
+ * tools, vmx, workstation, and boot components, as well as Windows, Mac, and
+ * FreeBSD builds. Also disabled for clang builds.
+ */
+#if defined(VM_X86_64) && !defined(VMCORE) && !defined(VMKBOOT) && \
+ !defined(VMX86_DESKTOP) && !defined(VMX86_TOOLS) && !defined(__APPLE__) && \
+ !defined(_WIN32) && !defined(__FreeBSD__) && !defined(__clang__)
+
+#include <x86sse.h>
+
+/*
+ * In the kernel we disable preemption during SSE sections, so we limit each
+ * section to 16 block updates (where each block is 64 bytes); this is on the
+ * order of 1-2 microseconds.
+ */
+#define SHA1_SSE_BLOCKS_PER_ITERATION 16
+
+void SHA1_Transform_SSSE3_ASM(uint32 *hash,
+ const uint8 *input,
+ uint64 numBlocks);
+
+/*
+ * Returns TRUE if we were able to use SSSE3 to apply the transform. See
+ * SHA1Transform for the function semantics.
+ */
+static INLINE Bool
+SHA1TransformSSSE3(uint32 state[5], // IN/OUT
+ const unsigned char *buffer, // IN
+ uint32 numBlocks) // IN
+{
+ static int useSSE = -1;
+ X86SSE_SaveState save;
+
+ ASSERT(useSSE == -1 || useSSE == 0 || useSSE == 1);
+
+ /* This is safe even if multiple threads race here. */
+ if (useSSE == -1) {
+ useSSE = X86SSE_IsSSSE3Supported();
+ }
+
+ if (useSSE == 0) {
+ return FALSE;
+ }
+
+ /*
+ * In debug mode, don't use SSE some of the time to make
+ * sure the non-SSE version is tested as well.
+ */
+ if (vmx86_debug && RDTSC() % 101 < 20) {
+ return FALSE;
+ }
+
+#ifdef VMKERNEL
+ if (!INTERRUPTS_ENABLED()) {
+ return FALSE;
+ }
+#endif
+
+ while (numBlocks > 0) {
+ uint32 blocksInIter = MIN(numBlocks, SHA1_SSE_BLOCKS_PER_ITERATION);
+
+ X86SSE_Prologue(&save);
+ SHA1_Transform_SSSE3_ASM(state, buffer, blocksInIter);
+ X86SSE_Epilogue(&save);
+
+ numBlocks -= blocksInIter;
+ buffer += blocksInIter * 64;
+ }
+
+ return TRUE;
+}
+
+#else
+
+static INLINE Bool
+SHA1TransformSSSE3(uint32 state[5],
+ const unsigned char *buffer,
+ uint32 numBlocks)
+{
+ return FALSE;
+}
+
+#endif
+
+
/* If the endianess is not defined (it is done in string.h of glibc 2.1.1), we
default to LE --hpreg */
#ifndef LITTLE_ENDIAN
@@ -97,6 +189,13 @@ A million repetitions of "a"
#define F2(w,x,y) (((w|x)&y)|(w&x))
#define F3(w,x,y) (w^x^y)
+/* Initialization vectors. */
+static const uint32 sha1InitVec[5] = { 0x67452301,
+ 0xEFCDAB89,
+ 0x98BADCFE,
+ 0x10325476,
+ 0xC3D2E1F0 };
+
typedef union {
unsigned char c[64];
uint32 l[16];
@@ -141,7 +240,7 @@ R(CHAR64LONG16 *block, uint32 *f, int i)
/* Hash a single 512-bit block. This is the core of the algorithm. */
static void
-_SHA1Transform(uint32 state[5], unsigned char buffer[64])
+SHA1TransformNoSSE(uint32 state[5], unsigned char buffer[64])
{
int i;
uint32 f[5];
@@ -162,37 +261,56 @@ _SHA1Transform(uint32 state[5], unsigned char buffer[64])
}
}
-#ifdef SHA1HANDSOFF
-static void
-SHA1Transform(uint32 state[5], const unsigned char buffer[64])
-#else
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * SHA1Transform --
+ *
+ * Applies the SHA-1 transform on one or more 64-byte block buffers.
+ *
+ * Results:
+ * state is updated.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
static void
-SHA1Transform(uint32 state[5], unsigned char buffer[64])
-#endif
+SHA1Transform(uint32 state[5], // IN/OUT
+ const unsigned char *buffer, // IN
+ uint32 numBlocks) // IN
{
-#ifdef SHA1HANDSOFF
- unsigned char workspace[64];
-
- /* Do not do that work in _SHA1Transform, otherwise gcc 2.7.2.3 will go
- south and allocate a stack frame of 0x9c8 bytes, that immediately
- leads to a stack smash and a host reset */
- memcpy(workspace, buffer, sizeof(workspace));
- _SHA1Transform(state, workspace);
-#else
- _SHA1Transform(state, buffer);
-#endif
+ uint32 i;
+
+ if (SHA1TransformSSSE3(state, buffer, numBlocks)) {
+ return;
+ }
+
+ for (i = 0; i < numBlocks; i++) {
+ unsigned char workspace[64];
+
+ /*
+ * Do not do that work in SHA1TransformNoSSE, otherwise gcc 2.7.2.3 will
+ * go south and allocate a stack frame of 0x9c8 bytes, that immediately
+ * leads to a stack smash and a host reset
+ */
+ memcpy(workspace, buffer, sizeof(workspace));
+ SHA1TransformNoSSE(state, workspace);
+ buffer += 64;
+ }
}
/* SHA1Init - Initialize new context */
void SHA1Init(SHA1_CTX* context)
{
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
+ uint32 i;
+ for (i = 0; i < 5; i++) {
+ context->state[i] = sha1InitVec[i];
+ }
context->count[0] = context->count[1] = 0;
}
VMK_KERNEL_EXPORT(SHA1Init);
@@ -200,32 +318,41 @@ VMK_KERNEL_EXPORT(SHA1Init);
/* Run your data through this. */
-#ifdef SHA1HANDSOFF
void SHA1Update(SHA1_CTX* context,
const unsigned char *data,
size_t len)
-#else
-void SHA1Update(SHA1_CTX* context,
- unsigned char *data,
- size_t len)
-#endif
{
- size_t i, j;
+ size_t curOfs, numRemaining;
- j = (context->count[0] >> 3) & 63;
+ /* Current offset inside the current buffer. */
+ curOfs = (context->count[0] >> 3) & 63;
if ((context->count[0] += (uint32) (len << 3)) < (len << 3))
context->count[1]++;
context->count[1] += (uint32) (len >> 29);
- if ((j + len) > 63) {
- memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64) {
- SHA1Transform(context->state, &data[i]);
+
+ numRemaining = 64 - curOfs;
+
+ if (len >= numRemaining) {
+ /* Complete the current buffer and update. */
+ memcpy(&context->buffer[curOfs], data, numRemaining);
+ SHA1Transform(context->state, context->buffer, 1);
+ data += numRemaining;
+ len -= numRemaining;
+ curOfs = 0;
+
+ /* Update with any complete 64-byte buffers. */
+ if (len >= 64) {
+ size_t numBlocks = len / 64;
+
+ SHA1Transform(context->state, data, numBlocks);
+ data += 64 * numBlocks;
+ len -= 64 * numBlocks;
}
- j = 0;
}
- else i = 0;
- memcpy(&context->buffer[j], &data[i], len - i);
+
+ /* Copy over whatever is left. */
+ ASSERT(len + curOfs < 64);
+ memcpy(&context->buffer[curOfs], data, len);
}
VMK_KERNEL_EXPORT(SHA1Update);
@@ -256,9 +383,47 @@ void SHA1Final(unsigned char digest[SHA1_HASH_LEN], SHA1_CTX* context)
memset(context->state, 0, SHA1_HASH_LEN);
memset(context->count, 0, 8);
memset(&finalcount, 0, 8);
-//#ifdef SHA1HANDSOFF
-// /* make SHA1Transform overwrite it's own static vars */
-// SHA1Transform(context->state, context->buffer);
-//#endif
}
VMK_KERNEL_EXPORT(SHA1Final);
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * SHA1RawBufferHash --
+ *
+ * Finds the SHA-1 of a "raw" buffer, without doing any preprocessing (does
+ * NOT add the 0x80 byte, 0x00 padding, and length encoding required for
+ * the result to be a proper message digest).
+ *
+ * Useful if the buffer already contains the preprocessed data, or if
+ * we are computing and comparing hashes for fixed-size blocks.
+ *
+ * The buffer size must be a multiple of 64 bytes.
+ *
+ * !! WARNING !! Do not use unless you know what you are doing! This
+ * will NOT compute the "usual" digest of the given buffer.
+ *
+ * Results:
+ * result contains the 120-bit SHA-1 value.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void SHA1RawBufferHash(const void *data, // IN
+ uint32 size, // IN
+ uint32 result[5]) // OUT
+{
+ uint32 i;
+
+ ASSERT(size % 64 == 0);
+
+ for (i = 0; i < 5; i++) {
+ result[i] = sha1InitVec[i];
+ }
+ SHA1Transform(result, (const uint8 *) data, size / 64);
+}
+VMK_KERNEL_EXPORT(SHA1RawBufferHash);
diff --git a/open-vm-tools/lib/misc/sleep.c b/open-vm-tools/lib/misc/sleep.c
new file mode 100644
index 00000000..34b91ffc
--- /dev/null
+++ b/open-vm-tools/lib/misc/sleep.c
@@ -0,0 +1,92 @@
+/*********************************************************
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * sleep.c --
+ *
+ * Portable, signal-safe implementation of Util_Usleep and Util_Sleep.
+ */
+
+#include "vmware.h"
+#include "util.h"
+#include "hostinfo.h"
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Util_Usleep --
+ *
+ * Sleeps for at least usec microseconds. If interrupted by a signal,
+ * goes back to sleep.
+ *
+ * This function is a drop-in replacement for usleep(3), so the argument is
+ * long because usleep(3) takes a long.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A delay.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Util_Usleep(long usec) // IN
+{
+ VmTimeType t_end, t;
+
+ t_end = Hostinfo_SystemTimerUS() + usec;
+
+ do {
+ usleep(usec);
+ t = Hostinfo_SystemTimerUS();
+ usec = t_end - t;
+ } while (t < t_end);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Util_Sleep --
+ *
+ * Sleeps for at least sec seconds. If interrupted by a signal,
+ * goes back to sleep.
+ *
+ * This function is a drop-in replacement for sleep(3), so the argument is
+ * unsigned int because sleep(3) takes unsigned int.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A delay.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Util_Sleep(unsigned int sec) // IN
+{
+ Util_Usleep((long)sec * 1000 * 1000);
+}
diff --git a/open-vm-tools/lib/misc/strutil.c b/open-vm-tools/lib/misc/strutil.c
index 501607df..1ba23127 100644
--- a/open-vm-tools/lib/misc/strutil.c
+++ b/open-vm-tools/lib/misc/strutil.c
@@ -95,8 +95,7 @@ StrUtil_GetNextToken(unsigned int *index, // IN/OUT: Index to start at
length = *index - startIndex;
ASSERT(length);
- token = (char *)malloc(length + 1 /* NUL */);
- VERIFY(token);
+ token = Util_SafeMalloc(length + 1 /* NUL */);
memcpy(token, str + startIndex, length);
token[length] = '\0';
@@ -462,7 +461,7 @@ StrUtil_StrToSizet(size_t *out, // OUT: The output value
ASSERT(str);
errno = 0;
-#if defined VM_X86_64
+#if defined VM_64BIT
ASSERT_ON_COMPILE(sizeof *out == sizeof(uint64));
# if defined(_WIN32)
*out = _strtoui64(str, &ptr, 0);
@@ -1122,8 +1121,7 @@ StrUtil_SafeStrcat(char **prefix, // IN/OUT
/* Check for overflow */
VERIFY((size_t)-1 - plen > slen + 1);
- tmp = realloc(*prefix, plen + slen + 1 /* NUL */);
- VERIFY(tmp);
+ tmp = Util_SafeRealloc(*prefix, plen + slen + 1 /* NUL */);
memcpy(tmp + plen, str, slen + 1 /* NUL */);
*prefix = tmp;
diff --git a/open-vm-tools/lib/misc/timeutil.c b/open-vm-tools/lib/misc/timeutil.c
index b0837a88..c4d78b5a 100644
--- a/open-vm-tools/lib/misc/timeutil.c
+++ b/open-vm-tools/lib/misc/timeutil.c
@@ -73,15 +73,9 @@ static Bool TimeUtilIsValidDate(unsigned int year,
* a lookup table
*/
-static int TimeUtilFindIndexAndNameByUTCOffset(int utcStdOffMins,
- const char **ptzName);
-
-#if defined(_WIN32)
-/*
- * Function to find Windows TZ Index by scanning registry
- */
-static int Win32TimeUtilLookupZoneIndex(const char* targetName);
-#endif
+static int TimeUtilFindIndexAndName(int utcStdOffMins,
+ const char *englishTzName,
+ const char **ptzName);
/*
@@ -840,9 +834,9 @@ TimeUtil_GetTimeFormat(int64 utcTime, // IN
timeStr, ARRAYSIZE(timeStr));
if (showDate && showTime) {
- return Str_Asprintf(NULL, "%s %s", dateStr, timeStr);
+ return Str_SafeAsprintf(NULL, "%s %s", dateStr, timeStr);
} else {
- return Str_Asprintf(NULL, "%s", showDate ? dateStr : timeStr);
+ return Util_SafeStrdup(showDate ? dateStr : timeStr);
}
#else
@@ -1032,11 +1026,16 @@ TimeUtil_UTCTimeToSystemTime(const __time64_t utcTime, // IN
*
* TimeUtil_GetLocalWindowsTimeZoneIndexAndName --
*
- * Gets Windows TZ Index and Name for local time zone.
+ * Determines the name and index for the computer's current time zone. The
+ * name is always the name of the time zone in standard time, even if Daylight
+ * Saving is currently in effect. This name is not localized, and is
+ * intended to be used when Easy Installing a Vista or later guest.
*
* Results:
- * -1 if there is any error, else the Windows Time Zone ID of the
- * current timezone (non-negative value).
+ * The index of the computer's current time zone. The name of the time zone
+ * in standard time is returned in *ptzName. The caller is responsible for
+ * freeing the returned string with free.
+ * If an error occurs, returns -1 and sets *ptzName to NULL.
*
* Side effects:
* On non-Win32 platforms, calls localtime_r() which sets globals
@@ -1050,27 +1049,38 @@ TimeUtil_GetLocalWindowsTimeZoneIndexAndName(char **ptzName) // OUT: returning
int utcStdOffMins = 0;
int winTimeZoneIndex = (-1);
const char *tzNameByUTCOffset = NULL;
+ char *englishTzName = NULL;
*ptzName = NULL;
#if defined(_WIN32)
-
{
- TIME_ZONE_INFORMATION tz;
- if (GetTimeZoneInformation(&tz) == TIME_ZONE_ID_INVALID) {
+ /*
+ * Hosted products don't support XP hosts anymore, but we use
+ * GetProcAddress instead of linking statically to
+ * GetDynamicTimeZoneInformation to avoid impacting Tools and Cascadia,
+ * which consume this lib and still need to run on XP.
+ */
+ DYNAMIC_TIME_ZONE_INFORMATION tzInfo = {0};
+ typedef DWORD (WINAPI* PFNGetTZInfo)(PDYNAMIC_TIME_ZONE_INFORMATION);
+ PFNGetTZInfo pfnGetTZInfo = NULL;
+
+ pfnGetTZInfo =
+ (PFNGetTZInfo) GetProcAddress(GetModuleHandleW(L"kernel32"),
+ "GetDynamicTimeZoneInformation");
+
+ if (pfnGetTZInfo == NULL || pfnGetTZInfo(&tzInfo) == TIME_ZONE_ID_INVALID) {
return (-1);
}
+ /*
+ * Save the unlocalized time zone name. We use it below to look up the
+ * time zone's index.
+ */
+ englishTzName = Unicode_AllocWithUTF16(tzInfo.TimeZoneKeyName);
+
/* 'Bias' = diff between UTC and local standard time */
- utcStdOffMins = 0 - tz.Bias; // already in minutes
-
- /* Find Windows TZ index */
- *ptzName = Unicode_AllocWithUTF16(tz.StandardName);
- winTimeZoneIndex = Win32TimeUtilLookupZoneIndex(*ptzName);
- if (winTimeZoneIndex < 0) {
- Unicode_Free(*ptzName);
- *ptzName = NULL;
- }
+ utcStdOffMins = 0 - tzInfo.Bias; // already in minutes
}
#else // NOT _WIN32
@@ -1113,15 +1123,17 @@ TimeUtil_GetLocalWindowsTimeZoneIndexAndName(char **ptzName) // OUT: returning
#endif
- /* If we don't have it yet, look up windowsCode. */
- if (winTimeZoneIndex < 0) {
- winTimeZoneIndex = TimeUtilFindIndexAndNameByUTCOffset(utcStdOffMins,
- &tzNameByUTCOffset);
- if (winTimeZoneIndex >= 0) {
- *ptzName = Unicode_AllocWithUTF8(tzNameByUTCOffset);
- }
+ /* Look up the name and index in a table. */
+ winTimeZoneIndex = TimeUtilFindIndexAndName(utcStdOffMins, englishTzName,
+ &tzNameByUTCOffset);
+
+ if (winTimeZoneIndex >= 0) {
+ *ptzName = Unicode_AllocWithUTF8(tzNameByUTCOffset);
}
+ free(englishTzName);
+ englishTzName = NULL;
+
return winTimeZoneIndex;
}
@@ -1321,14 +1333,15 @@ TimeUtilLoadDate(TimeUtil_Date *d, // IN/OUT
/*
*----------------------------------------------------------------------
*
- * TimeUtilFindIndexAndNameByUTCOffset --
+ * TimeUtilFindIndexAndName --
*
- * Private function. Scans a table for a given UTC-to-Standard
- * offset and returns the Windows TZ Index of the first match
- * found together with its Windows TZ Name.
+ * Given a time zone's offset from UTC and optionally its name, returns
+ * the time zone's Windows index and its name in standard time.
*
* Results:
- * Returns Windows TZ Index (>=0) if found, else -1.
+ * If the time zone is found in the table, returns the index and stores
+ * the name in *ptzName. The caller must not free the returned string.
+ * If the time zone is not found, returns -1 and sets *ptzName to NULL.
*
* Side effects:
* None.
@@ -1336,12 +1349,13 @@ TimeUtilLoadDate(TimeUtil_Date *d, // IN/OUT
*----------------------------------------------------------------------
*/
static int
-TimeUtilFindIndexAndNameByUTCOffset(int utcStdOffMins, // IN: offset (in minutes)
- const char **ptzName) // OUT: returning TZ Name
+TimeUtilFindIndexAndName(int utcStdOffMins, // IN: offset (in minutes)
+ const char *englishTzName, // IN/OPT: The English TZ name
+ const char **ptzName) // OUT: returning TZ Name
{
static struct _tzinfo {
int winTzIndex;
- char winTzName[256];
+ const char *winTzName;
int utcStdOffMins;
} TABLE[] = {
@@ -1349,10 +1363,11 @@ TimeUtilFindIndexAndNameByUTCOffset(int utcStdOffMins, // IN: offset (in mi
* These values are from Microsoft's TimeZone documentation:
*
* http://technet.microsoft.com/en-us/library/cc749073.aspx
+ *
+ * All time zones that have the same offset must be grouped together.
*/
{ 0, "Dateline Standard Time", -720 }, // -12
- { 1, "Samoa Standard Time", -660 }, // -11
{ 2, "Hawaiian Standard Time", -600 }, // -10
{ 3, "Alaskan Standard Time", -540 }, // -9
{ 4, "Pacific Standard Time", -480 }, // -8
@@ -1389,42 +1404,43 @@ TimeUtilFindIndexAndNameByUTCOffset(int utcStdOffMins, // IN: offset (in mi
{ 130, "GTB Standard Time", 120 }, // +2
{ 135, "Israel Standard Time", 120 }, // +2
{ 140, "South Africa Standard Time", 120 }, // +2
- { 145, "Russian Standard Time", 180 }, // +3
{ 150, "Arab Standard Time", 180 }, // +3
{ 155, "E. Africa Standard Time", 180 }, // +3
{ 158, "Arabic Standard Time", 180 }, // +3
{ 160, "Iran Standard Time", 210 }, // +3.5
+ { 145, "Russian Standard Time", 240 }, // +4
{ 165, "Arabian Standard Time", 240 }, // +4
{ 170, "Caucasus Standard Time", 240 }, // +4
{ 175, "Afghanistan Standard Time", 270 }, // +4.5
- { 180, "Ekaterinburg Standard Time", 300 }, // +5
{ 185, "West Asia Standard Time", 300 }, // +5
{ 190, "India Standard Time", 330 }, // +5.5
+ { 200, "Sri Lanka Standard Time", 330 }, // +5.5
{ 193, "Nepal Standard Time", 345 }, // +5.75
+ { 180, "Ekaterinburg Standard Time", 360 }, // +6
{ 195, "Central Asia Standard Time", 360 }, // +6
- { 200, "Sri Lanka Standard Time", 360 }, // +6
- { 201, "N. Central Asia Standard Time", 360 }, // +6
{ 203, "Myanmar Standard Time", 390 }, // +6.5
+ { 201, "N. Central Asia Standard Time", 420 }, // +7
{ 205, "SE Asia Standard Time", 420 }, // +7
- { 207, "North Asia Standard Time", 420 }, // +7
{ 210, "China Standard Time", 480 }, // +8
+ { 207, "North Asia Standard Time", 480 }, // +8
{ 215, "Singapore Standard Time", 480 }, // +8
{ 220, "Taipei Standard Time", 480 }, // +8
{ 225, "W. Australia Standard Time", 480 }, // +8
- { 227, "North Asia East Standard Time", 480 }, // +8
- { 230, "Korea Standard Time", 540 }, // +9
{ 235, "Tokyo Standard Time", 540 }, // +9
- { 240, "Yakutsk Standard Time", 540 }, // +9
+ { 230, "Korea Standard Time", 540 }, // +9
+ { 227, "North Asia East Standard Time", 540 }, // +9
{ 245, "AUS Central Standard Time", 570 }, // +9.5
{ 250, "Cen. Australia Standard Time", 570 }, // +9.5
{ 255, "AUS Eastern Standard Time", 600 }, // +10
{ 260, "E. Australia Standard Time", 600 }, // +10
{ 265, "Tasmania Standard Time", 600 }, // +10
- { 270, "Vladivostok Standard Time", 600 }, // +10
+ { 240, "Yakutsk Standard Time", 600 }, // +10
{ 275, "West Pacific Standard Time", 600 }, // +10
{ 280, "Central Pacific Standard Time", 660 }, // +11
- { 285, "Fiji Standard Time", 720 }, // +12
+ { 270, "Vladivostok Standard Time", 660 }, // +11
{ 290, "New Zealand Standard Time", 720 }, // +12
+ { 285, "Fiji Standard Time", 720 }, // +12
+ { 1, "Samoa Standard Time", 780 }, // +13
{ 300, "Tonga Standard Time", 780 }};// +13
size_t tableSize = ARRAYSIZE(TABLE);
@@ -1433,120 +1449,41 @@ TimeUtilFindIndexAndNameByUTCOffset(int utcStdOffMins, // IN: offset (in mi
*ptzName = NULL;
- /* XXX Finds the first match, not necessariy the right match! */
+ /*
+ * Search for the first time zone that has the passed-in offset. Then, if the
+ * caller also passed a name, search the time zones with that offset for a
+ * time zone with that name.
+ *
+ * If the caller does not pass a name, this loop returns the first time zone
+ * that it finds with the given offset. Because the UTC offset does not uniquely
+ * identify a time zone, this function can return a time zone that is not what
+ * the caller intended. For an example, see bug 1159642. Callers should pass
+ * a time zone name whenever possible.
+ */
for (look = 0; look < tableSize; look++) {
if (TABLE[look].utcStdOffMins == utcStdOffMins) {
+ /* We found a time zone with the right offset. */
tzIndex = TABLE[look].winTzIndex;
*ptzName = TABLE[look].winTzName;
- break;
- }
- }
-
- return tzIndex;
-}
+ /* Compare names if the caller passed a name. */
+ while (englishTzName != NULL &&
+ look < tableSize &&
+ TABLE[look].utcStdOffMins == utcStdOffMins) {
+ if (strcmp(englishTzName, TABLE[look].winTzName) == 0) {
+ *ptzName = TABLE[look].winTzName;
+ return TABLE[look].winTzIndex;
+ }
-#ifdef _WIN32
-/*
- *----------------------------------------------------------------------
- *
- * Win32TimeUtilLookupZoneIndex --
- *
- * Private function. Gets current Std time zone name using Windows
- * API, then scans the registry to find the information about that zone,
- * and extracts the TZ Index.
- *
- * Parameters:
- * targetName Standard-time zone name to look for.
- *
- * Results:
- * Returns Windows TZ Index (>=0) if found.
- * Returns -1 if not found or if any error was encountered.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-static int Win32TimeUtilLookupZoneIndex(const char* targetName)
-{
- int timeZoneIndex = (-1);
- HKEY parentKey, childKey;
- char childKeyName[255];
- int keyIndex, childKeyLen=255;
- DWORD rv;
-
- /* Open parent key containing timezone child keys */
- if (Win32U_RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "SOFTWARE\\"
- "Microsoft\\"
- "Windows NT\\"
- "CurrentVersion\\"
- "Time Zones",
- 0, KEY_READ, &parentKey) != ERROR_SUCCESS) {
- /* Failed to open registry */
- return (-1);
- }
+ look++;
+ }
- /* Scan child keys, stopping if name is found */
- keyIndex = 0;
- while (
- timeZoneIndex < 0 &&
- Win32U_RegEnumKeyEx(parentKey, keyIndex, childKeyName, &childKeyLen,
- 0,0,0,0) == ERROR_SUCCESS) {
- char *std;
- DWORD stdSize;
-
- /* Open child key */
- rv = Win32U_RegOpenKeyEx(parentKey, childKeyName, 0, KEY_READ, &childKey);
- if (rv != ERROR_SUCCESS) {
- continue;
+ break;
}
-
- /* Get size of "Std" value */
- if (Win32U_RegQueryValueEx(childKey, "Std", 0, 0,
- NULL, &stdSize) == ERROR_SUCCESS) {
-
- /* Get value of "Std" */
- std = (char*) calloc(stdSize+1, sizeof(char));
- if (std != NULL) {
- if (Win32U_RegQueryValueEx(childKey, "Std", 0, 0, (LPBYTE) std,
- &stdSize) == ERROR_SUCCESS) {
-
- /* Make sure there is at least one EOS */
- std[stdSize] = '\0';
-
- /* Is this the name we want? */
- if (!strcmp(std, targetName)) {
- /* yes: look up value of "Index" */
- DWORD val = 0;
- DWORD valSize = sizeof(val);
-
- if (Win32U_RegQueryValueEx(childKey, "Index", 0, 0,
- (LPBYTE) &val,
- &valSize) == ERROR_SUCCESS) {
- timeZoneIndex = val;
- }
- }
- }
- free(std);
- }
- }
-
- /* close this child key */
- RegCloseKey(childKey);
-
- /* reset for next child key */
- childKeyLen = 255;
- keyIndex++;
}
- /* Close registry parent key */
- RegCloseKey(parentKey);
-
- return timeZoneIndex;
+ return tzIndex;
}
-#endif // _WIN32
/*
diff --git a/open-vm-tools/lib/misc/util_misc.c b/open-vm-tools/lib/misc/util_misc.c
index 3b07aa41..473cc8b8 100644
--- a/open-vm-tools/lib/misc/util_misc.c
+++ b/open-vm-tools/lib/misc/util_misc.c
@@ -53,6 +53,8 @@
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <pthread.h>
+#elif defined(__sun__)
+#include <thread.h>
#endif
#if defined(__APPLE__)
@@ -205,7 +207,7 @@ Util_GetCanonicalPathForHash(const char *path) // IN: UTF-8
*-----------------------------------------------------------------------------
*/
-static char*
+static char *
UtilGetLegacyEncodedString(const char *path) // IN: UTF-8
{
char *ret = NULL;
@@ -332,10 +334,10 @@ Util_CanonicalPathsIdentical(const char *path1, // IN:
Bool
Util_IsAbsolutePath(const char *path) // IN: path to check
{
-#if defined(__linux__) || defined(__APPLE__)
+#if defined __linux__ || defined __APPLE__ || defined __FreeBSD__ || defined sun
// path[0] is valid even for the empty string.
return path && path[0] == DIRSEPC;
-#elif defined(_WIN32)
+#elif defined _WIN32
// if the length is 2, path[2] will be valid because of the null terminator.
if (!path || strlen(path) < 2) {
return FALSE;
@@ -414,43 +416,6 @@ Util_GetPrime(unsigned n0) // IN:
}
-#if defined(linux) && !defined(__ANDROID__)
-/*
- * Android has its own gettid. gettid has been declared in
- * <sys/linux-unistd.h> and defined as an extern function in <unistd.h>.
- */
-
-/*
- *-----------------------------------------------------------------------------
- *
- * gettid --
- *
- * Retrieve unique thread identification suitable for kill or setpriority.
- * Do not call this function directly, use Util_GetCurrentThreadId()
- * instead.
- *
- * Results:
- * Unique thread identification on success.
- * (pid_t)-1 on error, errno set (when kernel does not support this call)
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static INLINE
-pid_t gettid(void)
-{
-#if defined(SYS_gettid)
- return (pid_t)syscall(SYS_gettid);
-#else
- return -1;
-#endif
-}
-#endif
-
-
/*
*-----------------------------------------------------------------------------
*
@@ -459,6 +424,8 @@ pid_t gettid(void)
* Retrieves a unique thread identification suitable to identify a thread
* to kill it or change its scheduling priority.
*
+ * The tid is NOT guaranteed to be correct across fork().
+ *
* Results:
* Unique thread identification on success.
* ASSERTs on failure (should not happen).
@@ -472,48 +439,53 @@ pid_t gettid(void)
Util_ThreadID
Util_GetCurrentThreadId(void)
{
-#if defined(linux) || defined __ANDROID__
+#if defined(__linux__) && !defined(__ANDROID__)
/*
- * It is possible that two threads can enter gettid() path simultaneously,
- * both eventually clearing useTid to zero. It does not matter - only
- * problem which can happen is that useTid will be set to zero twice.
- * And it has no impact on useTid value...
+ * Linux does not declare gettid, but the raw syscall
+ * works fine. We must supply our own TLS caching.
*/
-
- static int useTid = 1;
-#if defined(VMX86_SERVER) && defined(GLIBC_VERSION_25)
- static __thread pid_t tid = -1;
-#else
- pid_t tid;
-#endif
-
-
- if (useTid) {
-#if defined(VMX86_SERVER) && defined(GLIBC_VERSION_25)
- if (tid != -1) {
- return tid;
- }
-#endif
- tid = gettid();
- if (tid != (pid_t)-1) {
- return tid;
- }
- ASSERT(errno == ENOSYS);
- useTid = 0;
+#if defined(GLIBC_VERSION_23)
+ static __thread pid_t tid;
+ if (UNLIKELY(tid == 0)) {
+ tid = (pid_t)syscall(SYS_gettid);
+ ASSERT(tid != -1); // All kernels that support TLS also implement gettid
}
- tid = getpid();
- ASSERT(tid != (pid_t)-1);
-
return tid;
-#elif defined(sun)
- pid_t tid;
-
- tid = getpid();
- ASSERT(tid != (pid_t)-1);
+#else
+ /*
+ * Always a syscall, but glibc-2.2 doesn't have __thread TLS so we couldn't
+ * cache anyway. We don't support kernels from before 2.4.11 when SYS_gettid
+ * was introduced, so no need to check the return value.
+ */
+ return (pid_t)syscall(SYS_gettid);
+#endif
- return tid;
-#elif defined(__APPLE__) || defined(__FreeBSD__)
- ASSERT_ON_COMPILE(sizeof(Util_ThreadID) == sizeof(pthread_t));
+#elif defined(__ANDROID__)
+ /*
+ * Bionic supplies a gettid implementation in <unistd.h> that
+ * natively uses TLS.
+ */
+ return gettid();
+#elif defined(__sun__)
+ /*
+ * The old thr_ API returns an integer thread identifier. It is
+ * still available with Solaris pthreads.
+ */
+ return thr_self();
+#elif defined(__APPLE__)
+ /*
+ * NB: do not use mach_thread_self here. mach_thread_self returns
+ * a reference and requires a matching mach_port_deallocate, which
+ * would take two syscalls instead of zero.
+ */
+ return pthread_mach_thread_np(pthread_self());
+#elif defined(__FreeBSD__)
+ /*
+ * These OSes do not implement OS-native thread IDs. You probably
+ * didn't need one anyway, but guess that pthread_self works
+ * well enough.
+ */
+ ASSERT_ON_COMPILE(sizeof(Util_ThreadID) >= sizeof(pthread_t));
return pthread_self();
#elif defined(_WIN32)
@@ -630,10 +602,10 @@ UtilGetLoginName(struct passwd *pwd) // IN/OPT: user passwd struct
*----------------------------------------------------------------------
*/
-static Unicode
-UtilDoTildeSubst(ConstUnicode user) // IN: name of user
+static char *
+UtilDoTildeSubst(const char *user) // IN: name of user
{
- Unicode str = NULL;
+ char *str = NULL;
struct passwd *pwd = NULL;
if (gHomeDirOverride) {
@@ -709,11 +681,11 @@ UtilDoTildeSubst(ConstUnicode user) // IN: name of user
#define UTIL_MAX_PATH_CHUNKS 100
-Unicode
-Util_ExpandString(ConstUnicode fileName) // IN file path to expand
+char *
+Util_ExpandString(const char *fileName) // IN file path to expand
{
- Unicode copy = NULL;
- Unicode result = NULL;
+ char *copy = NULL;
+ char *result = NULL;
int nchunk = 0;
char *chunks[UTIL_MAX_PATH_CHUNKS];
int chunkSize[UTIL_MAX_PATH_CHUNKS];
@@ -728,8 +700,7 @@ Util_ExpandString(ConstUnicode fileName) // IN file path to expand
/*
* quick exit
*/
- if (!Unicode_StartsWith(fileName, "~") &&
- Unicode_Find(fileName, "$") == UNICODE_INDEX_NOT_FOUND) {
+ if ((*fileName != '~') && (strchr(fileName, '$') == NULL)) {
return copy;
}
@@ -737,8 +708,8 @@ Util_ExpandString(ConstUnicode fileName) // IN file path to expand
* XXX Because the rest part of code depends pretty heavily from
* character pointer operations we want to leave it as-is and
* don't want to re-work it with using unicode library. However
- * it's acceptable only until our Unicode type is utf-8 and
- * until code below works correctly with utf-8.
+ * it's acceptable only until our Unicode type is UTF-8 and
+ * until code below works correctly with UTF-8.
*/
/*
@@ -764,7 +735,7 @@ Util_ExpandString(ConstUnicode fileName) // IN file path to expand
}
if (nchunk >= UTIL_MAX_PATH_CHUNKS) {
Log("%s: Filename \"%s\" has too many chunks.\n", __FUNCTION__,
- UTF8(fileName));
+ fileName);
goto out;
}
chunks[nchunk] = cp;
@@ -802,7 +773,7 @@ Util_ExpandString(ConstUnicode fileName) // IN file path to expand
for (i = 0; i < nchunk; i++) {
char save;
- Unicode expand = NULL;
+ char *expand = NULL;
char buf[100];
#if defined(_WIN32)
utf16_t bufW[100];
@@ -883,7 +854,7 @@ Util_ExpandString(ConstUnicode fileName) // IN file path to expand
chunks[i] = expand;
if (chunks[i] == NULL) {
Log("%s: Cannot allocate memory to expand \"%s\" in \"%s\".\n",
- __FUNCTION__, expand, UTF8(fileName));
+ __FUNCTION__, expand, fileName);
goto out;
}
chunkSize[i] = strlen(expand);
@@ -903,7 +874,7 @@ Util_ExpandString(ConstUnicode fileName) // IN file path to expand
}
if (result == NULL) {
Log("%s: Cannot allocate memory for the expansion of \"%s\".\n",
- __FUNCTION__, UTF8(fileName));
+ __FUNCTION__, fileName);
goto out;
}
cp = result;
diff --git a/open-vm-tools/lib/misc/vthreadBase.c b/open-vm-tools/lib/misc/vthreadBase.c
index 64da5d46..9b5959e5 100644
--- a/open-vm-tools/lib/misc/vthreadBase.c
+++ b/open-vm-tools/lib/misc/vthreadBase.c
@@ -70,8 +70,10 @@
#if defined __linux__
# include <features.h> /* for __GLIBC_PREREQ */
-# if __GLIBC_PREREQ(2, 3)
-# define HAVE_TLS
+# if defined __GLIBC_PREREQ
+# if __GLIBC_PREREQ(2, 3)
+# define HAVE_TLS
+# endif
# endif
#endif
@@ -1130,31 +1132,4 @@ VThreadBase_SetIsInSignal(VThreadID tid, // IN:
Atomic_Add(&base->signalNestCount, isInSignal ? 1 : -1);
}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * VThreadBase_SigMask --
- *
- * Wrapper for pthread_sigmask that uses VThreadBase's no-dependency
- * magic to get the effects of pthread_sigmask without actually
- * depending on lib/pthread.
- *
- * Results:
- * See 'man pthread_setmask'.
- *
- * Side effects:
- * See 'man pthread_setmask'.
- *
- *-----------------------------------------------------------------------------
- */
-
-int
-VThreadBase_SigMask(int how, // IN:
- const sigset_t *newmask, // IN:
- sigset_t *oldmask) // IN:
-{
- return pthread_sigmask(how, newmask, oldmask);
-}
#endif
diff --git a/open-vm-tools/lib/netUtil/netUtilLinux.c b/open-vm-tools/lib/netUtil/netUtilLinux.c
index df6013ab..13fcc1ea 100644
--- a/open-vm-tools/lib/netUtil/netUtilLinux.c
+++ b/open-vm-tools/lib/netUtil/netUtilLinux.c
@@ -348,87 +348,6 @@ NetUtil_GetIfName(int ifIndex) // IN: interface index
}
-# else // ifdef DUMMY_NETUTIL
-/*
- *-----------------------------------------------------------------------------
- *
- * NetUtil_GetIfIndex --
- *
- * Given an interface name, return its index.
- *
- * Results:
- * Returns a valid interface index on success or -1 on failure.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-int
-NetUtil_GetIfIndex(const char *ifName) // IN: interface name
-{
- struct ifreq ifreq;
- int fd = -1;
- int ifIndex = -1;
-
- memset(&ifreq, 0, sizeof ifreq);
- if (Str_Snprintf(ifreq.ifr_name, sizeof ifreq.ifr_name, "%s", ifName) == -1) {
- return -1;
- }
-
- if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
- return -1;
- }
-
- if (ioctl(fd, SIOCGIFINDEX, &ifreq) == 0) {
- ifIndex = ifreq.ifr_ifindex;
- }
-
- close(fd);
-
- return ifIndex;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * NetUtil_GetIfName --
- *
- * Given an interface index, return its name.
- *
- * Results:
- * Returns a valid interface name on success, NULL on failure.
- *
- * Side effects:
- * Caller is responsible for freeing the returned string.
- *
- *-----------------------------------------------------------------------------
- */
-
-char *
-NetUtil_GetIfName(int ifIndex) // IN: interface index
-{
- struct ifreq ifreq;
- char *ifName = NULL;
- int fd = -1;
-
- memset(&ifreq, 0, sizeof ifreq);
- ifreq.ifr_ifindex = ifIndex;
-
- if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
- return NULL;
- }
-
- if (ioctl(fd, SIOCGIFNAME, &ifreq) == 0) {
- ifName = Util_SafeStrdup(ifreq.ifr_name);
- }
-
- close(fd);
-
- return ifName;
-}
# endif // ifdef DUMMY_NETUTIL
diff --git a/open-vm-tools/lib/nicInfo/nicInfoPosix.c b/open-vm-tools/lib/nicInfo/nicInfoPosix.c
index a5fdc3fb..43246376 100644
--- a/open-vm-tools/lib/nicInfo/nicInfoPosix.c
+++ b/open-vm-tools/lib/nicInfo/nicInfoPosix.c
@@ -80,7 +80,7 @@
* bumped for this release, so instead I'm going to assume that appearance with
* that release of a new macro, RES_F_DNS0ERR, implies this API is available.
* (For internal builds, we'll know instantly when a build breaks. The down-
- * side is that this could cause some trouble for Open VM Tools users. ,_,)
+ * side is that this could cause some trouble for open-vm-tools users. ,_,)
*
* resolv.h version IPv6 API __RES
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/open-vm-tools/lib/panic/panic.c b/open-vm-tools/lib/panic/panic.c
index 99b6bd09..f3305080 100644
--- a/open-vm-tools/lib/panic/panic.c
+++ b/open-vm-tools/lib/panic/panic.c
@@ -31,6 +31,7 @@
# include <Windows.h>
#else // Posix
# include <unistd.h>
+# include <signal.h>
#endif // Win32 vs Posix
#include "vmware.h"
@@ -289,13 +290,38 @@ Panic_LoopOnPanic(void)
void
Panic_BreakOnPanic(void)
{
-#ifdef _WIN32
+#if defined(_WIN32)
if (Panic_GetBreakOnPanic()) {
Warning("Panic: breaking into debugger\n");
DebugBreak();
}
-#else
- /* XXX: Linux experts: is there any equivalent of attaching a JIT debugger? */
+#else // Posix
+ switch (panicState.breakOnPanic) {
+ case PanicBreakLevel_Never:
+ break;
+ case PanicBreakLevel_IfDebuggerAttached:
+ {
+ void (*handler)(int);
+ handler = signal(SIGTRAP, SIG_IGN);
+
+ /*
+ * INT3 is not always ignored, so explicitely use kill() here.
+ */
+ kill(getpid(), SIGTRAP);
+
+ signal(SIGTRAP, handler);
+ }
+ break;
+ default:
+ case PanicBreakLevel_Always:
+ Warning("Panic: breaking into debugger\n");
+# if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
+ __asm__ __volatile__ ("int3");
+# else
+ kill(getpid(), SIGTRAP);
+# endif
+ break;
+ }
#endif
}
@@ -366,7 +392,11 @@ Panic_GetBreakOnPanic(void)
}
}
#else
- /* XXX: Linux experts? How do you know if you're being ptraced? */
+ /*
+ * This case is handled by Panic_BreakOnPanic for Posix as there is no
+ * portable way to know if we're being debugged other than actually
+ * trapping into the debugger.
+ */
#endif
break;
default:
@@ -507,7 +537,7 @@ Panic_Panic(const char *format,
case 0:
break;
case 1:
- Log("%s", buf);
+ Log("PANIC: %s", buf);
Log("Panic loop\n");
default:
fprintf(stderr, "Panic loop\n");
@@ -528,7 +558,7 @@ Panic_Panic(const char *format,
* Log panic information.
*/
- Log("%s", buf);
+ Log("PANIC: %s", buf);
Util_Backtrace(0);
/*
diff --git a/open-vm-tools/lib/pollGtk/pollGtk.c b/open-vm-tools/lib/pollGtk/pollGtk.c
index 98d736f1..e09fe15f 100644
--- a/open-vm-tools/lib/pollGtk/pollGtk.c
+++ b/open-vm-tools/lib/pollGtk/pollGtk.c
@@ -1473,8 +1473,7 @@ PollGtkBasicCallback(gpointer data) // IN: The eventEntry
void
Poll_InitGtk(void)
{
- static GStaticMutex mx = G_STATIC_MUTEX_INIT;
- static volatile int inited = 0;
+ static volatile gsize inited = 0;
static const PollImpl gtkImpl =
{
@@ -1487,10 +1486,9 @@ Poll_InitGtk(void)
PollLockingAlwaysEnabled,
};
- g_static_mutex_lock(&mx);
- if (!inited) {
+ if (g_once_init_enter(&inited)) {
+ gsize didInit = 1;
Poll_InitWithImpl(&gtkImpl);
- inited = 1;
+ g_once_init_leave(&inited, didInit);
}
- g_static_mutex_unlock(&mx);
}
diff --git a/open-vm-tools/lib/printer/Makefile.in b/open-vm-tools/lib/printer/Makefile.in
deleted file mode 100644
index f2a74b7a..00000000
--- a/open-vm-tools/lib/printer/Makefile.in
+++ /dev/null
@@ -1,532 +0,0 @@
-# Makefile.in generated by automake 1.10 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-################################################################################
-### Copyright (C) 2007-2015 VMware, Inc. All rights reserved.
-###
-### This program is free software; you can redistribute it and/or modify
-### it under the terms of version 2 of the GNU General Public License as
-### published by the Free Software Foundation.
-###
-### This program is distributed in the hope that it will be useful,
-### but WITHOUT ANY WARRANTY; without even the implied warranty of
-### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-### GNU General Public License for more details.
-###
-### You should have received a copy of the GNU General Public License
-### along with this program; if not, write to the Free Software
-### Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-################################################################################
-
-VPATH = @srcdir@
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = lib/printer
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/m4/vmtools.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_CLEAN_FILES =
-LTLIBRARIES = $(noinst_LTLIBRARIES)
-libPrinter_la_LIBADD =
-am_libPrinter_la_OBJECTS = printer.lo
-libPrinter_la_OBJECTS = $(am_libPrinter_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
-depcomp = $(SHELL) $(top_srcdir)/config/depcomp
-am__depfiles_maybe = depfiles
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
-SOURCES = $(libPrinter_la_SOURCES)
-DIST_SOURCES = $(libPrinter_la_SOURCES)
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-COMMON_PLUGIN_INSTALLDIR = @COMMON_PLUGIN_INSTALLDIR@
-COMMON_XLIBS = @COMMON_XLIBS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CUNIT_CPPFLAGS = @CUNIT_CPPFLAGS@
-CUNIT_LIBS = @CUNIT_LIBS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DNET_CPPFLAGS = @DNET_CPPFLAGS@
-DNET_LIBS = @DNET_LIBS@
-DOT = @DOT@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-FUSE_CPPFLAGS = @FUSE_CPPFLAGS@
-FUSE_LIBS = @FUSE_LIBS@
-GLIB2_CPPFLAGS = @GLIB2_CPPFLAGS@
-GLIB2_LIBS = @GLIB2_LIBS@
-GMODULE_CPPFLAGS = @GMODULE_CPPFLAGS@
-GMODULE_LIBS = @GMODULE_LIBS@
-GOBJECT_CPPFLAGS = @GOBJECT_CPPFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
-GREP = @GREP@
-GTHREAD_CPPFLAGS = @GTHREAD_CPPFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
-GTKMM_CPPFLAGS = @GTKMM_CPPFLAGS@
-GTKMM_LIBS = @GTKMM_LIBS@
-GTK_CPPFLAGS = @GTK_CPPFLAGS@
-GTK_LIBS = @GTK_LIBS@
-HAVE_DOT = @HAVE_DOT@
-HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@
-HGFS_LIBS = @HGFS_LIBS@
-ICU_CPPFLAGS = @ICU_CPPFLAGS@
-ICU_LIBS = @ICU_LIBS@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INSTVMSG = @INSTVMSG@
-KERNEL_RELEASE = @KERNEL_RELEASE@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIBVMTOOLS_LIBADD = @LIBVMTOOLS_LIBADD@
-LIB_AUTH_CPPFLAGS = @LIB_AUTH_CPPFLAGS@
-LIB_IMPERSONATE_CPPFLAGS = @LIB_IMPERSONATE_CPPFLAGS@
-LIB_USER_CPPFLAGS = @LIB_USER_CPPFLAGS@
-LINUXINCLUDE = @LINUXINCLUDE@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-MODULES = @MODULES@
-MODULES_DIR = @MODULES_DIR@
-MODULES_OS = @MODULES_OS@
-MSCGEN = @MSCGEN@
-MSCGEN_DIR = @MSCGEN_DIR@
-MSPACK_CPPFLAGS = @MSPACK_CPPFLAGS@
-MSPACK_LIBS = @MSPACK_LIBS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJEXT = @OBJEXT@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PAM_CPPFLAGS = @PAM_CPPFLAGS@
-PAM_LIBS = @PAM_LIBS@
-PAM_PREFIX = @PAM_PREFIX@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PLUGIN_CPPFLAGS = @PLUGIN_CPPFLAGS@
-PLUGIN_LDFLAGS = @PLUGIN_LDFLAGS@
-PROCPS_CPPFLAGS = @PROCPS_CPPFLAGS@
-PROCPS_LIBS = @PROCPS_LIBS@
-RANLIB = @RANLIB@
-RPCGEN = @RPCGEN@
-RPCGENFLAGS = @RPCGENFLAGS@
-RPCGEN_WRAPPER = @RPCGEN_WRAPPER@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-SSL_CPPFLAGS = @SSL_CPPFLAGS@
-SSL_LIBS = @SSL_LIBS@
-STRIP = @STRIP@
-SYSDIR = @SYSDIR@
-TARGET_OS = @TARGET_OS@
-TEST_PLUGIN_INSTALLDIR = @TEST_PLUGIN_INSTALLDIR@
-TOOLS_VERSION = @TOOLS_VERSION@
-VERSION = @VERSION@
-VGAUTH_LIBADD = @VGAUTH_LIBADD@
-VIX_LIBADD = @VIX_LIBADD@
-VMSVC_PLUGIN_INSTALLDIR = @VMSVC_PLUGIN_INSTALLDIR@
-VMTOOLS_CPPFLAGS = @VMTOOLS_CPPFLAGS@
-VMTOOLS_LIBS = @VMTOOLS_LIBS@
-VMUSR_PLUGIN_INSTALLDIR = @VMUSR_PLUGIN_INSTALLDIR@
-XCOMPOSITE_LIBS = @XCOMPOSITE_LIBS@
-XDR_LIBS = @XDR_LIBS@
-XERCES_CPPFLAGS = @XERCES_CPPFLAGS@
-XERCES_LIBS = @XERCES_LIBS@
-XMKMF = @XMKMF@
-XMLSECURITY_CPPFLAGS = @XMLSECURITY_CPPFLAGS@
-XMLSECURITY_LIBS = @XMLSECURITY_LIBS@
-XSM_LIBS = @XSM_LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_LIBS = @X_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-ac_vmw_lib_cfg = @ac_vmw_lib_cfg@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-have_cxx = @have_cxx@
-have_doxygen = @have_doxygen@
-have_genmarshal = @have_genmarshal@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-lt_ECHO = @lt_ECHO@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-noinst_LTLIBRARIES = libPrinter.la
-libPrinter_la_SOURCES = printer.c
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/printer/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --gnu lib/printer/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-clean-noinstLTLIBRARIES:
- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
- test "$$dir" != "$$p" || dir=.; \
- echo "rm -f \"$${dir}/so_locations\""; \
- rm -f "$${dir}/so_locations"; \
- done
-libPrinter.la: $(libPrinter_la_OBJECTS) $(libPrinter_la_DEPENDENCIES)
- $(LINK) $(libPrinter_la_OBJECTS) $(libPrinter_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printer.Plo@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
- fi
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
- fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
- else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-am
-all-am: Makefile $(LTLIBRARIES)
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
- mostlyclean-am
-
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-info: install-info-am
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-ps: install-ps-am
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-noinstLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
- pdf pdf-am ps ps-am tags uninstall uninstall-am
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/open-vm-tools/lib/printer/printer.c b/open-vm-tools/lib/printer/printer.c
deleted file mode 100644
index e6d8f755..00000000
--- a/open-vm-tools/lib/printer/printer.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/*********************************************************
- * Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation version 2.1 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *********************************************************/
-
-/*
- * printer.c --
- *
- * This file implements assorted printer related functionality.
- *
- * This library is currently only implemented for Win32, and uses
- * Win32 API functions that are only available for Windows NT and
- * later. However, this library is linked into code that runs on
- * Win9x, and thus dynamically loads its Win32 API functions
- * from DLL.
- *
- * Therefore, users of this library must call Printer_Init()
- * before calling anything else.
- */
-
-#ifdef _WIN32
-#undef WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
-#include "vmware.h"
-#include "err.h"
-#include "printer.h"
-#ifdef _WIN32
-#include "win32u.h"
-#endif
-
-#define LOGLEVEL_MODULE printer
-#include "loglevel_user.h"
-
-
-/*
- * State needed for dynamically loading functions from DLLs.
- */
-
-#ifdef _WIN32
-HMODULE winspoolDll = NULL;
-
-typedef BOOL (WINAPI *AddPrinterConnectionFunc)(LPTSTR);
-typedef BOOL (WINAPI *SetDefaultPrinterFunc)(LPCTSTR);
-typedef BOOL (WINAPI *GetDefaultPrinterFunc)(LPTSTR, LPDWORD);
-
-AddPrinterConnectionFunc addPrinterConnectionFunc = NULL;
-GetDefaultPrinterFunc getDefaultPrinterFunc = NULL;
-SetDefaultPrinterFunc setDefaultPrinterFunc = NULL;
-#endif
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Printer_GetDefault --
- *
- * Get the default system printer name. The returned string is
- * allocated.
- *
- * (Currently only implemented on Windows.)
- *
- * Results:
- * Name of default printer
- * NULL on failure (or if there is no default).
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-char *
-Printer_GetDefault(void)
-{
-#ifdef _WIN32
- char *printerName = NULL;
- DWORD bufSize = 0;
- DWORD error;
- Bool success;
-
- /* Make sure function has been loaded. */
- if (!getDefaultPrinterFunc) {
- Log("%s: DLL not loaded\n", __FUNCTION__);
- ASSERT(FALSE);
-
- return NULL;
- }
-
- /* Find the necessary buffer size. */
- success = getDefaultPrinterFunc(printerName, &bufSize);
- error = Err_Errno();
- if (success) {
- Log("%s: Didn't fail with zero buffer\n", __FUNCTION__);
-
- return NULL;
- }
-
- if (error != ERROR_INSUFFICIENT_BUFFER) {
- Log("%s: Unexpected failure %d: %s\n", error,
- __FUNCTION__, Err_Errno2String(error));
-
- return NULL;
- }
-
- printerName = malloc(bufSize);
- if (!printerName) {
- Log("%s: Memory allocation failure\n", __FUNCTION__);
-
- return NULL;
- }
-
- success = getDefaultPrinterFunc(printerName, &bufSize);
- if (!success) {
- error = Err_Errno();
- Log("%s: Failed to get default printer\n", __FUNCTION__);
- free(printerName);
-
- return NULL;
- }
-
- return printerName;
-
-#else
- NOT_IMPLEMENTED();
- return NULL;
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Printer_SetDefault --
- *
- * Set the default system printer name.
- *
- * (Currently only implemented on Windows.)
- *
- * Results:
- * TRUE on success
- * FALSE on failure
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-Printer_SetDefault(char const *printerName) // IN
-{
-#ifdef _WIN32
- DWORD error;
-
- /* Make sure function has been loaded. */
- if (!setDefaultPrinterFunc) {
- Log("%s: DLL not loaded\n", __FUNCTION__);
- ASSERT(FALSE);
-
- return FALSE;
- }
-
- /*
- * Attempt to set the default printer.
- */
-
- if (!setDefaultPrinterFunc(printerName)) {
- error = Err_Errno();
- Log("%s: Unable to SetDefaultPrinter %d: %s\n", __FUNCTION__,
- error, Err_Errno2String(error));
-
- return FALSE;
- }
-
- return TRUE;
-
-#else
- NOT_IMPLEMENTED();
- return FALSE;
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Printer_AddConnection --
- *
- * Add a connection to the given printer for the current user.
- * (Win32 only)
- *
- * Printer connections are per-user, so this code must be run in
- * a user's login session in order to work. (Error code 2 is
- * returned otherwise, e.g. if this code is run from a service.)
- *
- * Results:
- * TRUE on success
- * FALSE on failure
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-Printer_AddConnection(char *printerName, // IN: Name of printer to add
- int *sysError) // OUT: System error code (errno)
-{
-#ifdef _WIN32
- DWORD error = ERROR_SUCCESS;
- Bool success = TRUE;
-
- ASSERT(printerName);
- ASSERT(sysError);
-
- /* Make sure function has been loaded. */
- if (!addPrinterConnectionFunc) {
- Log("%s: DLL not loaded\n", __FUNCTION__);
- ASSERT(FALSE);
- return FALSE;
- }
-
- /* Try to add the printer. */
- if (!addPrinterConnectionFunc((LPSTR)printerName)) {
- error = Err_Errno();
- Log("%s: Failed to add printer %s : %d %s\n", __FUNCTION__,
- printerName, error, Err_Errno2String(error));
- success = FALSE;
- }
-
- *sysError = error;
-
- return success;
-
-#else
- NOT_IMPLEMENTED();
-
- return FALSE;
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Printer_Init --
- *
- * Load the libraries for needed Win32 API functions. This is
- * necessary because this code is used in the Tools in Win9x guests,
- * and Win9x lacks support for some of these functions, so we can't
- * statically link them.
- *
- * Results:
- * TRUE on success
- * FALSE on failure
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-Printer_Init(void)
-{
-#ifdef _WIN32
- DWORD error;
-
- /*
- * Try to load the necessary library.
- */
- winspoolDll = Win32U_LoadLibrary("Winspool.drv");
- if (!winspoolDll) {
- error = Err_Errno();
- Log("%s: Failed to load Winspool.drv %d: %s\n", __FUNCTION__,
- error, Err_Errno2String(error));
-
- Log("%s: Trying to load Winspool as Winspool.dll...\n", __FUNCTION__);
- winspoolDll = Win32U_LoadLibrary("Winspool");
- if (!winspoolDll) {
- error = Err_Errno();
- Log("%s: Failed to load Winspool.dll %d: %s\n", __FUNCTION__,
- error, Err_Errno2String(error));
- Log("Unable to load Winspool, giving up.\n");
-
- return FALSE;
- }
- }
-
- /* Load individual functions. */
- getDefaultPrinterFunc = (GetDefaultPrinterFunc)GetProcAddress(winspoolDll,
- "GetDefaultPrinterA");
- if (!getDefaultPrinterFunc) {
- error = Err_Errno();
- Log("%s: Failed to load GetDefaultPrinter %d: %s\n", __FUNCTION__,
- error, Err_Errno2String(error));
- goto error;
- }
-
- setDefaultPrinterFunc = (SetDefaultPrinterFunc)GetProcAddress(winspoolDll,
- "SetDefaultPrinterA");
- if (!setDefaultPrinterFunc) {
- error = Err_Errno();
- Log("%s: Failed to load SetDefaultPrinter %d: %s\n", __FUNCTION__,
- error, Err_Errno2String(error));
- goto error;
- }
-
- addPrinterConnectionFunc = (AddPrinterConnectionFunc)GetProcAddress(winspoolDll,
- "AddPrinterConnectionA");
- if (!addPrinterConnectionFunc) {
- error = Err_Errno();
- Log("%s: Failed to load AddPrinterConnection %d: %s\n", __FUNCTION__,
- error, Err_Errno2String(error));
- goto error;
- }
-
- return TRUE;
-
- error:
- addPrinterConnectionFunc = NULL;
- setDefaultPrinterFunc = NULL;
- getDefaultPrinterFunc = NULL;
- return FALSE;
-
-#else
- /* Allow this to succeed for non-Win32. */
- return TRUE;
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Printer_Cleanup --
- *
- * Cleanup all the state loaded by Printer_Init().
- *
- * Results:
- * TRUE on success
- * FALSE on failure
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-Printer_Cleanup(void)
-{
-#ifdef _WIN32
- DWORD error;
-
- if (!winspoolDll) {
- Log("%s: Printer library not loaded.\n", __FUNCTION__);
-
- return FALSE;
- }
-
- addPrinterConnectionFunc = NULL;
- setDefaultPrinterFunc = NULL;
- getDefaultPrinterFunc = NULL;
-
- if (!FreeLibrary(winspoolDll)) {
- error = Err_Errno();
- Log("%s: Failed to FreeLibrary %d: %s\n", __FUNCTION__,
- error, Err_Errno2String(error));
- winspoolDll = NULL;
-
- return FALSE;
- }
-
- winspoolDll = NULL;
-
- return TRUE;
-
-#else
- /* Allow this to succeed for non-Win32. */
- return TRUE;
-#endif
-}
diff --git a/open-vm-tools/lib/procMgr/procMgrPosix.c b/open-vm-tools/lib/procMgr/procMgrPosix.c
index c938bb90..d0e78a4f 100644
--- a/open-vm-tools/lib/procMgr/procMgrPosix.c
+++ b/open-vm-tools/lib/procMgr/procMgrPosix.c
@@ -24,10 +24,6 @@
*
*/
-#ifndef VMX86_DEVEL
-
-#endif
-
// pull in setresuid()/setresgid() if possible
#define _GNU_SOURCE
#include <unistd.h>
@@ -82,10 +78,14 @@
#include "su.h"
#include "str.h"
#include "strutil.h"
-#include "fileIO.h"
#include "codeset.h"
#include "unicode.h"
+#ifdef USERWORLD
+#include <vm_basic_types.h>
+#include <vmkuserstatus.h>
+#include <vmkusercompat.h>
+#endif
/*
* All signals that:
@@ -108,7 +108,7 @@ static int const cSignals[] = {
struct ProcMgr_AsyncProc {
pid_t waiterPid; // pid of the waiter process
pid_t resultPid; // pid of the process created for the client
- FileIODescriptor fd; // fd to write to when the child is done
+ int fd; // fd to write to when the child is done
Bool validExitCode;
int exitCode;
};
@@ -1303,6 +1303,38 @@ ProcMgrStartProcess(char const *cmd, // IN: UTF-8 encoded cmd
envpCurrent = Unicode_GetAllocList(envp, -1, STRING_ENCODING_DEFAULT);
}
+#ifdef USERWORLD
+ do {
+ static const char filePath[] = "/bin/sh";
+ char * const argv[] = { "sh", "++group=host/vim/tmp",
+ "-c", cmdCurrent, NULL };
+ int initFds[] = { STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO };
+ int workingDirFd;
+ VmkuserStatus_Code status;
+ int outPid;
+
+ workingDirFd = open(workingDir != NULL ? workingDir : "/tmp", O_RDONLY);
+ status = VmkuserCompat_ForkExec(filePath,
+ argv,
+ envpCurrent,
+ workingDirFd,
+ initFds,
+ ARRAYSIZE(initFds),
+ geteuid(),
+ getegid(),
+ 0,
+ &outPid);
+ if (workingDirFd >= 0) {
+ close(workingDirFd);
+ }
+ if (VmkuserStatus_IsOK(status)) {
+ pid = (pid_t)outPid;
+ } else {
+ VmkuserStatus_CodeToErrno(status, &errno);
+ pid = -1;
+ }
+ } while (FALSE);
+#else
pid = fork();
if (pid == -1) {
@@ -1360,6 +1392,7 @@ ProcMgrStartProcess(char const *cmd, // IN: UTF-8 encoded cmd
Panic("Unable to execute the \"%s\" shell command: %s.\n\n",
cmd, strerror(errno));
}
+#endif
/*
* Parent
@@ -1367,7 +1400,7 @@ ProcMgrStartProcess(char const *cmd, // IN: UTF-8 encoded cmd
free(cmdCurrent);
free(workDir);
- Unicode_FreeList(envpCurrent, -1);
+ Util_FreeStringList(envpCurrent, -1);
return pid;
}
@@ -1385,12 +1418,12 @@ ProcMgrStartProcess(char const *cmd, // IN: UTF-8 encoded cmd
* FALSE on failure or if an error occurred (detail is displayed)
*
* Side effects:
- * Prevents zombification of the process.
+ * Prevents zombification of the process.
*
*----------------------------------------------------------------------
*/
-static Bool
+static Bool
ProcMgrWaitForProcCompletion(pid_t pid, // IN
Bool *validExitCode, // OUT: Optional
int *exitCode) // OUT: Optional
@@ -1464,8 +1497,7 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
Bool validExitCode;
int exitCode;
pid_t resultPid;
- FileIODescriptor readFd;
- FileIODescriptor writeFd;
+ int readFd, writeFd;
Debug("Executing async command: '%s' in working dir '%s'\n",
cmd, (userArgs && userArgs->workingDirectory) ? userArgs->workingDirectory : "");
@@ -1475,8 +1507,8 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
return NULL;
}
- readFd = FileIO_CreateFDPosix(fds[0], O_RDONLY);
- writeFd = FileIO_CreateFDPosix(fds[1], O_WRONLY);
+ readFd = fds[0];
+ writeFd = fds[1];
pid = fork();
@@ -1503,7 +1535,7 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
*/
maxfd = sysconf(_SC_OPEN_MAX);
for (i = STDERR_FILENO + 1; i < maxfd; i++) {
- if (i != readFd.posix && i != writeFd.posix) {
+ if (i != readFd && i != writeFd) {
close(i);
}
}
@@ -1518,7 +1550,7 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
status = FALSE;
}
- FileIO_Close(&readFd);
+ close(readFd);
/*
* Only run the program if we have not already experienced a failure.
@@ -1534,8 +1566,7 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
* Send the child's pid back immediately, so that the caller can
* report the result pid back synchronously.
*/
- if (FileIO_Write(&writeFd, &childPid, sizeof childPid, NULL) !=
- FILEIO_SUCCESS) {
+ if (write(writeFd, &childPid, sizeof childPid) == -1) {
Warning("Waiter unable to write back to parent.\n");
/*
@@ -1560,9 +1591,8 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
* block waiting for data we'll never send.
*/
Debug("Writing the command %s a success to fd %x\n",
- status ? "was" : "was not", writeFd.posix);
- if (FileIO_Write(&writeFd, &status, sizeof status, NULL) !=
- FILEIO_SUCCESS) {
+ status ? "was" : "was not", writeFd);
+ if (write(writeFd, &status, sizeof status) == -1) {
Warning("Waiter unable to write back to parent\n");
/*
@@ -1573,8 +1603,7 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
exit(-1);
}
- if (FileIO_Write(&writeFd, &exitCode, sizeof exitCode , NULL) !=
- FILEIO_SUCCESS) {
+ if (write(writeFd, &exitCode, sizeof exitCode) == -1) {
Warning("Waiter unable to write back to parent\n");
/*
@@ -1585,7 +1614,7 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
exit(-1);
}
- FileIO_Close(&writeFd);
+ close(writeFd);
if (status &&
Signal_ResetGroupHandler(cSignals, olds, ARRAYSIZE(cSignals)) == 0) {
@@ -1605,13 +1634,13 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
* Parent
*/
- FileIO_Close(&writeFd);
+ close(writeFd);
+ writeFd = -1;
/*
* Read the pid of the child's child from the pipe.
*/
- if (FileIO_Read(&readFd, &resultPid, sizeof resultPid , NULL) !=
- FILEIO_SUCCESS) {
+ if (read(readFd, &resultPid, sizeof resultPid) != sizeof resultPid) {
Warning("Unable to read result pid from the pipe.\n");
/*
@@ -1636,18 +1665,18 @@ ProcMgr_ExecAsync(char const *cmd, // IN: UTF-8 command line
asyncProc = Util_SafeMalloc(sizeof *asyncProc);
asyncProc->fd = readFd;
- FileIO_Invalidate(&readFd);
+ readFd = -1;
asyncProc->waiterPid = pid;
asyncProc->validExitCode = FALSE;
asyncProc->exitCode = -1;
asyncProc->resultPid = resultPid;
abort:
- if (FileIO_IsValid(&readFd)) {
- FileIO_Close(&readFd);
+ if (readFd != -1) {
+ close(readFd);
}
- if (FileIO_IsValid(&writeFd)) {
- FileIO_Close(&writeFd);
+ if (writeFd != -1) {
+ close(writeFd);
}
return asyncProc;
@@ -1871,7 +1900,7 @@ ProcMgr_GetAsyncProcSelectable(ProcMgr_AsyncProc *asyncProc)
{
ASSERT(asyncProc);
- return asyncProc->fd.posix;
+ return asyncProc->fd;
}
@@ -1929,15 +1958,13 @@ ProcMgr_GetExitCode(ProcMgr_AsyncProc *asyncProc, // IN
if (asyncProc->waiterPid != -1) {
Bool status;
- if (FileIO_Read(&(asyncProc->fd), &status, sizeof status, NULL) !=
- FILEIO_SUCCESS) {
+ if (read(asyncProc->fd, &status, sizeof status) != sizeof status) {
Warning("Error reading async process status.\n");
goto exit;
}
- if (FileIO_Read(&(asyncProc->fd), &(asyncProc->exitCode),
- sizeof asyncProc->exitCode, NULL) !=
- FILEIO_SUCCESS) {
+ if (read(asyncProc->fd, &asyncProc->exitCode,
+ sizeof asyncProc->exitCode) != sizeof asyncProc->exitCode) {
Warning("Error reading async process status.\n");
goto exit;
}
@@ -1945,7 +1972,7 @@ ProcMgr_GetExitCode(ProcMgr_AsyncProc *asyncProc, // IN
asyncProc->validExitCode = TRUE;
Debug("Child w/ fd %x exited with code=%d\n",
- asyncProc->fd.posix, asyncProc->exitCode);
+ asyncProc->fd, asyncProc->exitCode);
}
*exitCode = asyncProc->exitCode;
@@ -1999,8 +2026,8 @@ ProcMgr_Free(ProcMgr_AsyncProc *asyncProc) // IN
}
#endif
- if ((asyncProc != NULL) && FileIO_IsValid(&(asyncProc->fd))) {
- FileIO_Close(&(asyncProc->fd));
+ if (asyncProc != NULL && asyncProc->fd != -1) {
+ close(asyncProc->fd);
}
free(asyncProc);
diff --git a/open-vm-tools/lib/procMgr/procMgrSolaris.c b/open-vm-tools/lib/procMgr/procMgrSolaris.c
index bceb32fe..f5a4cada 100644
--- a/open-vm-tools/lib/procMgr/procMgrSolaris.c
+++ b/open-vm-tools/lib/procMgr/procMgrSolaris.c
@@ -29,9 +29,22 @@
#include <dirent.h>
#include <errno.h>
#include <string.h>
+
+#if _FILE_OFFSET_BITS != 64
+# error FILE_OFFSET_BITS=64 required
+#endif
+/*
+ * Work around unnecessary blocking of FOB=64 in Sol10, fixed in Sol11
+ * See https://www.illumos.org/issues/2410
+ */
+#undef _FILE_OFFSET_BITS
#include <procfs.h>
+#define _FILE_OFFSET_BITS 64
+
#include <ctype.h>
#include <sys/param.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "vmware.h"
#include "procMgr.h"
@@ -42,22 +55,22 @@
#include "dynarray.h"
#include "su.h"
#include "str.h"
-#include "fileIO.h"
+#include "posix.h"
#include "codeset.h"
#include "unicode.h"
static Bool
-ReadArgsFromAddressSpaceFile(FileIODescriptor asFd,
+ReadArgsFromAddressSpaceFile(int asFd,
psinfo_t *psInfo,
DynBufArray *cmdLineArr);
static Bool
-ReadOffsetsFromAddressSpaceFile(FileIODescriptor asFd,
+ReadOffsetsFromAddressSpaceFile(int asFd,
psinfo_t *psInfo,
uintptr_t *argOffs);
static char *
-ExtractArgStringFromAddressSpaceFile(FileIODescriptor asFd,
+ExtractArgStringFromAddressSpaceFile(int asFd,
uintptr_t offset);
static char *
@@ -116,12 +129,10 @@ ProcMgr_ListProcesses(void)
psinfo_t procInfo;
size_t strLen = 0;
size_t numRead = 0;
- FileIODescriptor psInfoFd;
- FileIOResult res;
+ int psInfoFd = -1;
Bool cmdNameLookup = TRUE;
errno = 0;
- FileIO_Invalidate(&psInfoFd);
ent = readdir(dir);
if (ent == NULL) {
@@ -139,22 +150,18 @@ ProcMgr_ListProcesses(void)
Debug("Process id '%s' too large\n", ent->d_name);
continue;
}
- res = FileIO_Open(&psInfoFd,
- tempPath,
- FILEIO_OPEN_ACCESS_READ,
- FILEIO_OPEN);
- if (res != FILEIO_SUCCESS) {
- if ((res == FILEIO_FILE_NOT_FOUND) ||
- (res == FILEIO_NO_PERMISSION)) {
+ psInfoFd = Posix_Open(tempPath, O_RDONLY);
+ if (psInfoFd == -1) {
+ if (errno == ENOENT || errno == EACCES) {
continue;
} else {
goto exit;
}
}
- res = FileIO_Read(&psInfoFd, &procInfo, sizeof procInfo, &numRead);
- FileIO_Close(&psInfoFd);
- if (res != FILEIO_SUCCESS) {
+ numRead = read(psInfoFd, &procInfo, sizeof procInfo);
+ close(psInfoFd);
+ if (numRead != sizeof procInfo) {
goto exit;
}
@@ -308,8 +315,7 @@ ExtractCommandLineFromAddressSpaceFile(psinfo_t *procInfo, //IN: psinfo struct
int i;
char tempPath[MAXPATHLEN];
char *buf;
- FileIODescriptor asFd;
- FileIOResult res;
+ int asFd = -1;
DynBuf cmdLine;
DynBufArray args;
pid_t pid;
@@ -318,7 +324,6 @@ ExtractCommandLineFromAddressSpaceFile(psinfo_t *procInfo, //IN: psinfo struct
if (NULL != procCmdName) {
*procCmdName = NULL;
}
- FileIO_Invalidate(&asFd);
pid = procInfo->pr_pid;
if (Str_Snprintf(tempPath,
@@ -328,14 +333,10 @@ ExtractCommandLineFromAddressSpaceFile(psinfo_t *procInfo, //IN: psinfo struct
/* This should not happen. MAXPATHLEN should be large enough. */
ASSERT(FALSE);
}
- res = FileIO_Open(&asFd,
- tempPath,
- FILEIO_OPEN_ACCESS_READ,
- FILEIO_OPEN);
- if (res != FILEIO_SUCCESS) {
+ asFd = Posix_Open(tempPath, O_RDONLY);
+ if (asFd == -1) {
Warning("Could not open address space file for pid %"FMT64"d, %s\n",
- (int64_t)pid,
- FileIO_MsgError(res));
+ (int64_t)pid, strerror(errno));
return NULL;
}
@@ -375,7 +376,7 @@ ExtractCommandLineFromAddressSpaceFile(psinfo_t *procInfo, //IN: psinfo struct
buf = DynBuf_Detach(&cmdLine);
DynBuf_Destroy(&cmdLine);
}
- FileIO_Close(&asFd);
+ close(asFd);
return buf;
}
@@ -406,7 +407,7 @@ ExtractCommandLineFromAddressSpaceFile(psinfo_t *procInfo, //IN: psinfo struct
*/
static Bool
-ReadArgsFromAddressSpaceFile(FileIODescriptor asFd, //IN
+ReadArgsFromAddressSpaceFile(int asFd, //IN
psinfo_t *psInfo, //IN
DynBufArray *cmdLineArr) //OUT
{
@@ -508,14 +509,14 @@ fail:
*/
static Bool
-ReadOffsetsFromAddressSpaceFile(FileIODescriptor asFd, //IN
+ReadOffsetsFromAddressSpaceFile(int asFd, //IN
psinfo_t *psInfo, //IN
uintptr_t *argOffs) //OUT
{
int argc;
int i;
uintptr_t argv;
- FileIOResult res;
+ ssize_t res;
argc = psInfo->pr_argc;
argv = psInfo->pr_argv;
@@ -529,8 +530,8 @@ ReadOffsetsFromAddressSpaceFile(FileIODescriptor asFd, //IN
/*
* The offset for each arguments is sizeof uintptr_t bytes.
*/
- res = FileIO_Pread(&asFd, argOffs, argc * sizeof argv, argv);
- if (res != FILEIO_SUCCESS) {
+ res = pread(asFd, argOffs, argc * sizeof argv, argv);
+ if (res != argc * sizeof argv) {
return FALSE;
}
} else {
@@ -542,8 +543,8 @@ ReadOffsetsFromAddressSpaceFile(FileIODescriptor asFd, //IN
if (argOffs32 == NULL) {
return FALSE;
}
- res = FileIO_Pread(&asFd, argOffs32, argc * sizeof *argOffs32, argv);
- if (res != FILEIO_SUCCESS) {
+ res = pread(asFd, argOffs32, argc * sizeof *argOffs32, argv);
+ if (res != argc * sizeof *argOffs32) {
free (argOffs32);
return FALSE;
}
@@ -578,17 +579,17 @@ ReadOffsetsFromAddressSpaceFile(FileIODescriptor asFd, //IN
*/
static char *
-ExtractArgStringFromAddressSpaceFile(FileIODescriptor asFd, //IN
- uintptr_t offset) //IN
+ExtractArgStringFromAddressSpaceFile(int asFd, //IN
+ uintptr_t offset) //IN
{
int readSize = 32;
char *buf;
- FileIOResult res;
+ ssize_t res;
buf = Util_SafeMalloc(readSize * sizeof *buf);
while (1) {
- res = FileIO_Pread(&asFd, buf, readSize, offset);
- if (res != FILEIO_SUCCESS) {
+ res = pread(asFd, buf, readSize, offset);
+ if (res != readSize) {
goto fail;
}
if (Str_Strlen(buf, readSize) == readSize) {
diff --git a/open-vm-tools/lib/rpcChannel/rpcChannel.c b/open-vm-tools/lib/rpcChannel/rpcChannel.c
index 57e5ff48..39cd63ce 100644
--- a/open-vm-tools/lib/rpcChannel/rpcChannel.c
+++ b/open-vm-tools/lib/rpcChannel/rpcChannel.c
@@ -62,6 +62,13 @@ static RpcChannelCallback gRpcHandlers[] = {
static gboolean gUseBackdoorOnly = FALSE;
+/*
+ * Track the vSocket connection failure, so that we can
+ * avoid using vSockets until a channel reset/restart or
+ * the service itself gets restarted.
+ */
+static gboolean gVSocketFailed = FALSE;
+
/**
* Handler for a "ping" message. Does nothing.
*
@@ -91,6 +98,10 @@ RpcChannelRestart(gpointer _chan)
RpcChannelInt *chan = _chan;
RpcChannel_Stop(&chan->impl);
+ /* Clear vSocket channel failure */
+ Debug(LGPFX "Clearing backdoor behavior ...\n");
+ gVSocketFailed = FALSE;
+
if (!RpcChannel_Start(&chan->impl)) {
Warning("Channel restart failed [%d]\n", chan->rpcErrorCount);
if (chan->resetCb != NULL) {
@@ -144,6 +155,8 @@ RpcChannelCheckReset(gpointer _chan)
/* Reset was successful. */
Debug(LGPFX "Channel was reset successfully.\n");
chan->rpcErrorCount = 0;
+ Debug(LGPFX "Clearing backdoor behavior ...\n");
+ gVSocketFailed = FALSE;
if (chan->resetCb != NULL) {
chan->resetCb(&chan->impl, TRUE, chan->resetData);
@@ -656,7 +669,8 @@ RpcChannel_New(void)
{
RpcChannel *chan;
#if (defined(__linux__) && !defined(USERWORLD)) || defined(_WIN32)
- chan = gUseBackdoorOnly ? BackdoorChannel_New() : VSockChannel_New();
+ chan = (gUseBackdoorOnly || gVSocketFailed) ?
+ BackdoorChannel_New() : VSockChannel_New();
#else
chan = BackdoorChannel_New();
#endif
@@ -737,6 +751,12 @@ RpcChannel_Start(RpcChannel *chan)
Debug(LGPFX "Fallback to backdoor ...\n");
funcs->onStartErr(chan);
ok = BackdoorChannel_Fallback(chan);
+ /*
+ * As vSocket is not available, we stick the backdoor
+ * behavior until the channel is reset/restarted.
+ */
+ Debug(LGPFX "Sticking backdoor behavior ...\n");
+ gVSocketFailed = TRUE;
}
return ok;
diff --git a/open-vm-tools/lib/rpcIn/rpcin.c b/open-vm-tools/lib/rpcIn/rpcin.c
index 69c711c3..abe48e61 100644
--- a/open-vm-tools/lib/rpcIn/rpcin.c
+++ b/open-vm-tools/lib/rpcIn/rpcin.c
@@ -53,6 +53,8 @@
#undef VMTOOLS_USE_VSOCKET
#endif
+#include <ctype.h>
+
#if defined(VMTOOLS_USE_VSOCKET)
# include <glib.h>
# include "poll.h"
@@ -76,7 +78,7 @@
#include "message.h"
#include "rpcin.h"
#include "util.h"
-
+#include "system.h"
#if !defined(VMTOOLS_USE_GLIB)
#include "eventManager.h"
@@ -1409,6 +1411,88 @@ RpcInUpdateDelayTime(RpcIn *in) // IN
/*
*-----------------------------------------------------------------------------
*
+ * ByteDump --
+ *
+ * Return a \0 terminated string that keeps ascii characters
+ * but escapes non ascii ones.
+ *
+ * The output may be truncated if an internal buffer limit is reached.
+ *
+ * Result:
+ * Return a string that the caller should not free
+ *
+ * Side-effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static char *
+ByteDump(const char *buf,
+ size_t size)
+{
+#define BYTE_DUMP_LIMIT 128
+ static const char truncationTag[] = "...";
+ static char dumpBuffer[BYTE_DUMP_LIMIT + sizeof truncationTag];
+ size_t i, count, nPrintable, nBinary;
+
+ count = 0;
+ nPrintable = 0;
+ nBinary = 0;
+
+ if (! size) {
+ goto exit;
+ }
+
+ for (i = 0; i < size; ++i) {
+ unsigned char c = buf[i];
+ if (c == '\\') {
+ if ((BYTE_DUMP_LIMIT - count) < 2) {
+ break;
+ }
+ dumpBuffer[count++] = c;
+ dumpBuffer[count++] = c;
+ ++nPrintable;
+ } else if (isprint(c)) {
+ if ((BYTE_DUMP_LIMIT - count) < 1) {
+ break;
+ }
+ dumpBuffer[count++] = c;
+ ++nPrintable;
+ } else {
+ if ((BYTE_DUMP_LIMIT - count) < 3) {
+ break;
+ }
+ dumpBuffer[count++] = '\\';
+ Str_Snprintf(&dumpBuffer[count], 3, "%02x", c);
+ count += 2;
+ ++nBinary;
+ }
+ }
+
+ if (nBinary > nPrintable) {
+ return "(assumed/dropped binary data)";
+ }
+
+ if (i < size) {
+ /* Data is truncated */
+ int n = Str_Snprintf(&dumpBuffer[count], sizeof dumpBuffer - count,
+ "%s", truncationTag);
+ ASSERT(n);
+ count += n;
+ }
+
+exit:
+
+ dumpBuffer[count] = 0;
+
+ return dumpBuffer;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* RpcInLoop --
*
* Receives an RPC from the host.
@@ -1484,11 +1568,23 @@ RpcInLoop(void *clientData) // IN
}
if (repLen) {
- Debug("RpcIn: received %"FMTSZ"u bytes\n", repLen);
+ char *s = ByteDump(reply, repLen);
+ Debug("RpcIn: received %d bytes, content:\"%s\"\n", (int) repLen, s);
if (!RpcInExecRpc(in, reply, repLen, &errmsg)) {
goto error;
}
} else {
+ static uint64 lastPrintMilli = 0;
+ uint64 now = System_GetTimeMonotonic() * 10;
+ if ((now - lastPrintMilli) > 5000) {
+ /*
+ * Throttle the log to write one entry every 5 seconds
+ * this allow us to figure that tools side is polling for TCLO.
+ */
+ Debug("RpcIn: received 0 bytes, empty TCLO poll\n");
+ lastPrintMilli = now;
+ }
+
/*
* Nothing to execute
*/
diff --git a/open-vm-tools/lib/rpcOut/rpcout.c b/open-vm-tools/lib/rpcOut/rpcout.c
index 6d0014ab..2e5c326d 100644
--- a/open-vm-tools/lib/rpcOut/rpcout.c
+++ b/open-vm-tools/lib/rpcOut/rpcout.c
@@ -64,13 +64,37 @@
*/
struct RpcOut {
- Message_Channel *channel;
+ Message_Channel channel;
+ Bool started;
};
/*
*-----------------------------------------------------------------------------
*
+ * RpcOutInitialize --
+ *
+ * Initializes an already allocated RpcOut object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * See above.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+RpcOutInitialize(RpcOut *rpcOut)
+{
+ memset(rpcOut, 0, sizeof *rpcOut);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* RpcOut_Construct --
*
* Constructor for the RpcOut object
@@ -87,7 +111,9 @@ struct RpcOut {
RpcOut *
RpcOut_Construct(void)
{
- return (RpcOut *)calloc(1, sizeof(RpcOut));
+ RpcOut *rpcOut = malloc(sizeof *rpcOut);
+ RpcOutInitialize(rpcOut);
+ return rpcOut;
}
@@ -110,8 +136,8 @@ RpcOut_Construct(void)
void
RpcOut_Destruct(RpcOut *out) // IN
{
- ASSERT(out);
- ASSERT(out->channel == NULL);
+ ASSERT(out != NULL);
+ ASSERT(!out->started);
free(out);
}
@@ -120,9 +146,15 @@ RpcOut_Destruct(RpcOut *out) // IN
/*
*-----------------------------------------------------------------------------
*
- * RpcOut_start --
+ * RpcOut_startWithReceiveBuffer --
*
- * Open the channel
+ * Open the channel. This variant of RpcOut_start allows the
+ * caller to pre-allocate the receiver buffer, but by doing so it
+ * allows for some simple operations without the need to call
+ * malloc.
+ *
+ * Passing in NULL and size 0 will cause this function to fall
+ * back to using malloc.
*
* Result:
* TRUE on success
@@ -135,17 +167,41 @@ RpcOut_Destruct(RpcOut *out) // IN
*/
Bool
-RpcOut_start(RpcOut *out) // IN
+RpcOut_startWithReceiveBuffer(RpcOut *out, char *receiveBuffer,
+ size_t receiveBufferSize)
{
- ASSERT(out);
- ASSERT(out->channel == NULL);
- out->channel = Message_Open(RPCI_PROTOCOL_NUM);
- if (out->channel == NULL) {
+ ASSERT(out != NULL);
+ ASSERT(!out->started);
+ out->started = Message_OpenAllocated(RPCI_PROTOCOL_NUM, &out->channel,
+ receiveBuffer, receiveBufferSize);
+ if (!out->started) {
Debug("RpcOut: couldn't open channel with RPCI protocol\n");
- return FALSE;
}
+ return out->started;
+}
+
- return TRUE;
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * RpcOut_start --
+ *
+ * Open the channel
+ *
+ * Result:
+ * TRUE on success
+ * FALSE on failure
+ *
+ * Side-effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+RpcOut_start(RpcOut *out) // IN
+{
+ return RpcOut_startWithReceiveBuffer(out, NULL, 0);
}
@@ -182,25 +238,17 @@ RpcOut_send(RpcOut *out, // IN
size_t myRepLen;
Bool success;
- ASSERT(out);
-
- ASSERT(out->channel);
+ ASSERT(out != NULL);
+ ASSERT(out->started);
- if (out->channel == NULL) {
- *reply = "RpcOut: Channel is not active";
- *repLen = strlen(*reply);
-
- return FALSE;
- }
-
- if (Message_Send(out->channel, (const unsigned char *)request, reqLen) == FALSE) {
+ if (Message_Send(&out->channel, (const unsigned char *)request, reqLen) == FALSE) {
*reply = "RpcOut: Unable to send the RPCI command";
*repLen = strlen(*reply);
return FALSE;
}
- if (Message_Receive(out->channel, &myReply, &myRepLen) == FALSE) {
+ if (Message_Receive(&out->channel, &myReply, &myRepLen) == FALSE) {
*reply = "RpcOut: Unable to receive the result of the RPCI command";
*repLen = strlen(*reply);
@@ -243,20 +291,18 @@ RpcOut_send(RpcOut *out, // IN
Bool
RpcOut_stop(RpcOut *out) // IN
{
- Bool status;
+ Bool status = TRUE;
- ASSERT(out);
+ ASSERT(out != NULL);
- status = TRUE;
-
- if (out->channel) {
+ if (out->started) {
/* Try to close the channel */
- if (Message_Close(out->channel) == FALSE) {
+ if (Message_CloseAllocated(&out->channel) == FALSE) {
Debug("RpcOut: couldn't close channel\n");
status = FALSE;
}
- out->channel = NULL;
+ out->started = FALSE;
}
return status;
@@ -353,73 +399,47 @@ RpcOut_sendOne(char **reply, // OUT: Result
/*
*-----------------------------------------------------------------------------
*
- * RpcOut_SendOneRaw --
+ * RpcOutSendOneRawWork --
*
- * Make VMware execute a RPCI command
- *
- * VMware closes a channel when it detects that there has been no activity
- * on it for a while. Because we do not know how often this program will
- * make VMware execute a RPCI, we open/close one channel per RPCI command.
- *
- * This function sends a message over the backdoor without using
- * any of the Str_ functions on the request buffer; Str_Asprintf() in
- * particular uses FormatMessage on Win32, which corrupts some UTF-8
- * strings. Using this function directly instead of using RpcOut_SendOne()
- * avoids these problems.
- *
- * If this is not an issue, you can use RpcOut_sendOne(), which has
- * varargs.
- *
- * Note: It is the caller's responsibility to ensure that the RPCI command
- * followed by a space appear at the start of the request buffer. See
- * the command in RpcOut_sendOne for details.
- *
- * Return value:
- * TRUE on success. '*reply' contains an allocated result of the rpc
- * FALSE on error. '*reply' contains an allocated description of the
- * error or NULL.
- *
- *
- * Side effects:
- * None
+ * Helper function to make VMware execute a RPCI command. See
+ * RpcOut_SendOneRaw and RpcOut_SendOneRawPreallocated.
*
*-----------------------------------------------------------------------------
*/
-Bool
-RpcOut_SendOneRaw(void *request, // IN: RPCI command
- size_t reqLen, // IN: Size of request buffer
- char **reply, // OUT: Result
- size_t *repLen) // OUT: Length of the result
+static Bool
+RpcOutSendOneRawWork(void *request, // IN: RPCI command
+ size_t reqLen, // IN: Size of request buffer
+ char *callerReply, // IN: caller supplied reply buffer
+ size_t callerReplyLen, // IN: size of caller supplied buf
+ char **reply, // OUT: Result
+ size_t *repLen) // OUT: Length of the result
{
Bool status;
- RpcOut *out = NULL;
+ /* Stack allocate so this can be used in kernel logging. See 1389199. */
+ RpcOut out;
char const *myReply;
size_t myRepLen;
- status = FALSE;
-
Debug("Rpci: Sending request='%s'\n", (char *)request);
- out = RpcOut_Construct();
- if (out == NULL) {
- myReply = "RpcOut: Unable to create the RpcOut object";
- myRepLen = strlen(myReply);
-
- goto sent;
- } else if (RpcOut_start(out) == FALSE) {
+ RpcOutInitialize(&out);
+ if (!RpcOut_startWithReceiveBuffer(&out, callerReply, callerReplyLen)) {
myReply = "RpcOut: Unable to open the communication channel";
myRepLen = strlen(myReply);
+
+ if (callerReply != NULL) {
+ unsigned s = MIN(callerReplyLen - 1, myRepLen);
+ ASSERT(reply == NULL);
+ memcpy(callerReply, myReply, s);
+ callerReply[s] = '\0';
+ }
- goto sent;
- } else if (RpcOut_send(out, request, reqLen, &myReply, &myRepLen)
- == FALSE) {
- /* We already have the description of the error */
- goto sent;
+ return FALSE;
}
- status = TRUE;
+ status = RpcOut_send(&out, request, reqLen, &myReply, &myRepLen);
+ /* On failure, we already have the description of the error */
-sent:
Debug("Rpci: Sent request='%s', reply='%s', len=%"FMTSZ"u, status=%d\n",
(char *)request, myReply, myRepLen, status);
@@ -463,26 +483,103 @@ sent:
}
}
- if (out) {
- if (RpcOut_stop(out) == FALSE) {
- /*
- * We couldn't stop the channel. Free anything we allocated, give our
- * client a reply of NULL, and return FALSE.
- */
+ if (RpcOut_stop(&out) == FALSE) {
+ /*
+ * We couldn't stop the channel. Free anything we allocated, give our
+ * client a reply of NULL, and return FALSE.
+ */
- if (reply != NULL) {
- free(*reply);
- *reply = NULL;
- }
- Debug("Rpci: unable to close the communication channel\n");
- status = FALSE;
+ if (reply != NULL) {
+ free(*reply);
+ *reply = NULL;
}
-
- RpcOut_Destruct(out);
- out = NULL;
+ Debug("Rpci: unable to close the communication channel\n");
+ status = FALSE;
}
return status;
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * RpcOut_SendOneRaw --
+ *
+ * Make VMware execute a RPCI command
+ *
+ * VMware closes a channel when it detects that there has been no activity
+ * on it for a while. Because we do not know how often this program will
+ * make VMware execute a RPCI, we open/close one channel per RPCI command.
+ *
+ * This function sends a message over the backdoor without using
+ * any of the Str_ functions on the request buffer; Str_Asprintf() in
+ * particular uses FormatMessage on Win32, which corrupts some UTF-8
+ * strings. Using this function directly instead of using RpcOut_SendOne()
+ * avoids these problems.
+ *
+ * If this is not an issue, you can use RpcOut_sendOne(), which has
+ * varargs.
+ *
+ * Note: It is the caller's responsibility to ensure that the RPCI command
+ * followed by a space appear at the start of the request buffer. See
+ * the command in RpcOut_sendOne for details.
+ *
+ * Return value:
+ * TRUE on success. '*reply' contains an allocated result of the rpc
+ * FALSE on error. '*reply' contains an allocated description of the
+ * error or NULL.
+ *
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+RpcOut_SendOneRaw(void *request, // IN: RPCI command
+ size_t reqLen, // IN: Size of request buffer
+ char **reply, // OUT: Result
+ size_t *repLen) // OUT: Length of the result
+{
+ return RpcOutSendOneRawWork(request, reqLen, NULL, 0, reply, repLen);
+}
+
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * RpcOut_SendOneRawPreallocated --
+ *
+ * Make VMware execute a RPCI command.
+ *
+ * A variant of RpcOut_SendOneRaw in which the caller supplies the
+ * receive buffer instead of dynamically allocating it. This
+ * allows the caller to call this function in situations where
+ * malloc is not allowed. But if the response from the host is too
+ * large the rpc will fail instead of attempting to grow its own
+ * receive buffer.
+ *
+ *
+ * Return value:
+ * TRUE on success. 'reply' contains an allocated result of the rpc
+ * FALSE on error. 'reply' contains an allocated description of the
+ * error or NULL.
+ *
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+RpcOut_SendOneRawPreallocated(void *request, // IN: RPCI command
+ size_t reqLen, // IN: Size of request buffer
+ char *reply, // OUT: Result
+ size_t repLen) // IN: Length of the result
+{
+ return RpcOutSendOneRawWork(request, reqLen, reply, repLen, NULL, NULL);
+}
diff --git a/open-vm-tools/lib/rpcVmx/rpcvmx.c b/open-vm-tools/lib/rpcVmx/rpcvmx.c
index 40e26381..24c6203d 100644
--- a/open-vm-tools/lib/rpcVmx/rpcvmx.c
+++ b/open-vm-tools/lib/rpcVmx/rpcvmx.c
@@ -143,7 +143,7 @@ RpcVMX_Log(const char *fmt, ...)
* None.
*
* Side effects:
- * Lots of silly memory allocation.
+ * Sends the log command described above.
*
*----------------------------------------------------------------------------
*/
@@ -152,6 +152,7 @@ void
RpcVMX_LogV(const char *fmt, va_list args)
{
int payloadLen;
+ char receiveBuffer[16];
payloadLen = Str_Vsnprintf(RpcVMX.logBuf + RpcVMX.logOffset,
sizeof RpcVMX.logBuf - RpcVMX.logOffset,
@@ -165,7 +166,16 @@ RpcVMX_LogV(const char *fmt, va_list args)
payloadLen = sizeof RpcVMX.logBuf - RpcVMX.logOffset;
}
- RpcOut_SendOneRaw(RpcVMX.logBuf, RpcVMX.logOffset + payloadLen, NULL, NULL);
+ /*
+ * Use a pre-allocated receive buffer so that it's possible to
+ * perform the log without needing to call malloc. This makes
+ * RpcVMX_LogV suitable to be used in Windows kernel interrupt
+ * handlers. (It also makes it faster.) The log command only ever
+ * returns two character strings "1 " on success and "0 " on
+ * failure, so we don't need a sizeable buffer.
+ */
+ RpcOut_SendOneRawPreallocated(RpcVMX.logBuf, RpcVMX.logOffset + payloadLen,
+ receiveBuffer, sizeof receiveBuffer);
}
diff --git a/open-vm-tools/lib/slashProc/net.c b/open-vm-tools/lib/slashProc/net.c
index 489ddc4d..2ea7ded2 100644
--- a/open-vm-tools/lib/slashProc/net.c
+++ b/open-vm-tools/lib/slashProc/net.c
@@ -27,6 +27,7 @@
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
+#include <net/if.h>
#include <glib.h>
#include <glib/gstdio.h>
@@ -768,7 +769,7 @@ SlashProcNet_GetRoute6(void)
myEntry->rtmsg_metric = MatchToGuint64(myMatchInfo, 6, 16);
myEntry->rtmsg_flags = MatchToGuint64(myMatchInfo, 7, 16);
- MATCHEXPR(myMatchInfo, 8, myEntry->rtmsg_ifindex = NetUtil_GetIfIndex(MATCH));
+ MATCHEXPR(myMatchInfo, 8, myEntry->rtmsg_ifindex = if_nametoindex(MATCH));
badIteration:
g_free(myLine);
diff --git a/open-vm-tools/lib/string/str.c b/open-vm-tools/lib/string/str.c
index 62ecfe4d..484489bc 100644
--- a/open-vm-tools/lib/string/str.c
+++ b/open-vm-tools/lib/string/str.c
@@ -401,7 +401,7 @@ Str_Strnstr(const char *src, // IN:
*/
char *
-Str_Strcat(char *buf, // IN-OUT
+Str_Strcat(char *buf, // IN/OUT
const char *src, // IN
size_t maxSize) // IN
{
@@ -445,7 +445,7 @@ Str_Strcat(char *buf, // IN-OUT
*/
char *
-Str_Strncat(char *buf, // IN-OUT
+Str_Strncat(char *buf, // IN/OUT
size_t bufSize, // IN: Size of buf
const char *src, // IN: String to append
size_t n) // IN: Max chars of src to append
@@ -500,7 +500,7 @@ Str_Strncat(char *buf, // IN-OUT
*/
char *
-Str_Asprintf(size_t *length, // OUT
+Str_Asprintf(size_t *length, // OUT/OPT
const char *format, // IN
...) // IN
{
@@ -532,7 +532,7 @@ Str_Asprintf(size_t *length, // OUT
*/
char *
-Str_SafeAsprintf(size_t *length, // OUT
+Str_SafeAsprintf(size_t *length, // OUT/OPT
const char *format, // IN
...) // IN
{
@@ -572,7 +572,7 @@ Str_SafeAsprintf(size_t *length, // OUT
*/
static char *
-StrVasprintfInternal(size_t *length, // OUT:
+StrVasprintfInternal(size_t *length, // OUT/OPT:
const char *format, // IN:
va_list arguments, // IN:
Bool assertOnFailure) // IN:
@@ -654,7 +654,7 @@ StrVasprintfInternal(size_t *length, // OUT:
*/
char *
-Str_Vasprintf(size_t *length, // OUT
+Str_Vasprintf(size_t *length, // OUT/OPT
const char *format, // IN
va_list arguments) // IN
{
@@ -681,7 +681,7 @@ Str_Vasprintf(size_t *length, // OUT
*/
char *
-Str_SafeVasprintf(size_t *length, // OUT
+Str_SafeVasprintf(size_t *length, // OUT/OPT
const char *format, // IN
va_list arguments) // IN
{
@@ -873,7 +873,7 @@ Str_Wcscpy(wchar_t *buf, // OUT
*/
wchar_t *
-Str_Wcscat(wchar_t *buf, // IN-OUT
+Str_Wcscat(wchar_t *buf, // IN/OUT
const wchar_t *src, // IN
size_t maxSize) // IN: Size of buf, in wide-characters.
{
@@ -914,7 +914,7 @@ Str_Wcscat(wchar_t *buf, // IN-OUT
*/
wchar_t *
-Str_Wcsncat(wchar_t *buf, // IN-OUT
+Str_Wcsncat(wchar_t *buf, // IN/OUT
size_t bufSize, // IN: Size of buf, in wide-characters.
const wchar_t *src, // IN: String to append
size_t n) // IN: Max chars of src to append
@@ -964,13 +964,13 @@ Str_Wcsncat(wchar_t *buf, // IN-OUT
*/
unsigned char *
-Str_Mbscpy(char *buf, // OUT
- const char *src, // IN
- size_t maxSize) // IN
+Str_Mbscpy(char *buf, // OUT
+ const char *src, // IN
+ size_t maxSize) // IN
{
size_t len;
- len = strlen((const char *) src);
+ len = strlen(src);
if (len >= maxSize) {
Panic("%s:%d Buffer too small\n", __FILE__, __LINE__);
}
@@ -998,15 +998,15 @@ Str_Mbscpy(char *buf, // OUT
*/
unsigned char *
-Str_Mbscat(char *buf, // IN-OUT
- const char *src, // IN
- size_t maxSize) // IN
+Str_Mbscat(char *buf, // IN/OUT
+ const char *src, // IN
+ size_t maxSize) // IN
{
size_t bufLen;
size_t srcLen;
- bufLen = strlen((const char *) buf);
- srcLen = strlen((const char *) src);
+ bufLen = strlen(buf);
+ srcLen = strlen(src);
/* The first comparison checks for numeric overflow */
if (bufLen + srcLen < srcLen || bufLen + srcLen >= maxSize) {
@@ -1042,7 +1042,7 @@ Str_Mbscat(char *buf, // IN-OUT
*/
static wchar_t *
-StrVaswprintfInternal(size_t *length, // OUT:
+StrVaswprintfInternal(size_t *length, // OUT/OPT:
const wchar_t *format, // IN:
va_list arguments, // IN
Bool assertOnFailure) // IN
@@ -1111,7 +1111,7 @@ StrVaswprintfInternal(size_t *length, // OUT:
*/
wchar_t *
-Str_Aswprintf(size_t *length, // OUT
+Str_Aswprintf(size_t *length, // OUT/OPT
const wchar_t *format, // IN
...) // IN
{
@@ -1145,7 +1145,7 @@ Str_Aswprintf(size_t *length, // OUT
*/
wchar_t *
-Str_Vaswprintf(size_t *length, // OUT
+Str_Vaswprintf(size_t *length, // OUT/OPT
const wchar_t *format, // IN
va_list arguments) // IN
{
@@ -1170,7 +1170,7 @@ Str_Vaswprintf(size_t *length, // OUT
*/
wchar_t *
-Str_SafeAswprintf(size_t *length, // OUT
+Str_SafeAswprintf(size_t *length, // OUT/OPT
const wchar_t *format, // IN
...) // IN
{
@@ -1204,7 +1204,7 @@ Str_SafeAswprintf(size_t *length, // OUT
*/
wchar_t *
-Str_SafeVaswprintf(size_t *length, // OUT
+Str_SafeVaswprintf(size_t *length, // OUT/OPT
const wchar_t *format, // IN
va_list arguments) // IN
{
diff --git a/open-vm-tools/lib/stubs/Makefile.am b/open-vm-tools/lib/stubs/Makefile.am
index 755c2644..09b35dc0 100644
--- a/open-vm-tools/lib/stubs/Makefile.am
+++ b/open-vm-tools/lib/stubs/Makefile.am
@@ -20,7 +20,9 @@ noinst_LTLIBRARIES = libStubs.la
libStubs_la_SOURCES =
libStubs_la_SOURCES += stub-config.c
libStubs_la_SOURCES += stub-log.c
+libStubs_la_SOURCES += stub-debug.c
libStubs_la_SOURCES += stub-warning.c
+libStubs_la_SOURCES += stub-panic.c
libStubs_la_SOURCES += stub-user-msg.c
libStubs_la_SOURCES += stub-user-panic.c
libStubs_la_SOURCES += stub-user-util.c
diff --git a/open-vm-tools/lib/stubs/Makefile.in b/open-vm-tools/lib/stubs/Makefile.in
index 4750ddad..8b13c188 100644
--- a/open-vm-tools/lib/stubs/Makefile.in
+++ b/open-vm-tools/lib/stubs/Makefile.in
@@ -63,8 +63,9 @@ mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libStubs_la_LIBADD =
-am_libStubs_la_OBJECTS = stub-config.lo stub-log.lo stub-warning.lo \
- stub-user-msg.lo stub-user-panic.lo stub-user-util.lo
+am_libStubs_la_OBJECTS = stub-config.lo stub-log.lo stub-debug.lo \
+ stub-warning.lo stub-panic.lo stub-user-msg.lo \
+ stub-user-panic.lo stub-user-util.lo
libStubs_la_OBJECTS = $(am_libStubs_la_OBJECTS)
libStubsCS_la_LIBADD =
am__libStubsCS_la_SOURCES_DIST = stub-config.c stub-user-msg.c \
@@ -280,8 +281,9 @@ target_alias = @target_alias@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_LTLIBRARIES = libStubs.la libStubsCS.la
-libStubs_la_SOURCES = stub-config.c stub-log.c stub-warning.c \
- stub-user-msg.c stub-user-panic.c stub-user-util.c
+libStubs_la_SOURCES = stub-config.c stub-log.c stub-debug.c \
+ stub-warning.c stub-panic.c stub-user-msg.c stub-user-panic.c \
+ stub-user-util.c
libStubsCS_la_SOURCES = stub-config.c stub-user-msg.c \
stub-user-panic.c $(am__append_1)
all: all-am
@@ -338,8 +340,10 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stub-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stub-debug.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stub-log.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stub-msgfmt-fbsd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stub-panic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stub-user-msg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stub-user-panic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stub-user-util.Plo@am__quote@
diff --git a/open-vm-tools/lib/stubs/stub-config.c b/open-vm-tools/lib/stubs/stub-config.c
index 24479898..c71f4ce6 100644
--- a/open-vm-tools/lib/stubs/stub-config.c
+++ b/open-vm-tools/lib/stubs/stub-config.c
@@ -48,6 +48,15 @@ Config_GetLong(int32 defaultValue,
}
+double
+Config_GetDouble(double defaultValue,
+ const char *fmt,
+ ...)
+{
+ return defaultValue;
+}
+
+
char *
Config_GetString(const char *defaultValue,
const char *fmt, ...)
diff --git a/open-vm-tools/lib/stubs/stub-debug.c b/open-vm-tools/lib/stubs/stub-debug.c
new file mode 100644
index 00000000..a015673f
--- /dev/null
+++ b/open-vm-tools/lib/stubs/stub-debug.c
@@ -0,0 +1,46 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * stub-debug.c --
+ *
+ * Stub for Debug().
+ *
+ */
+
+#include <stdio.h>
+#include "str.h"
+
+
+void
+Debug(const char *fmt, ...)
+{
+#ifdef VMX86_DEBUG
+ char *str;
+ va_list args;
+
+ va_start(args, fmt);
+ str = Str_Vasprintf(NULL, fmt, args);
+ va_end(args);
+
+ if (str != NULL) {
+ fputs(str, stderr);
+ }
+#endif
+}
+
diff --git a/open-vm-tools/lib/stubs/stub-panic.c b/open-vm-tools/lib/stubs/stub-panic.c
new file mode 100644
index 00000000..615a8108
--- /dev/null
+++ b/open-vm-tools/lib/stubs/stub-panic.c
@@ -0,0 +1,57 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * stub-panic.c --
+ *
+ * Stub for lib/panic.
+ *
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "vm_assert.h"
+#include "str.h"
+
+
+void
+Panic(const char *fmt, ...)
+{
+ char *str;
+ va_list args;
+
+ va_start(args, fmt);
+ str = Str_Vasprintf(NULL, fmt, args);
+ va_end(args);
+
+ if (str != NULL) {
+ fputs(str, stderr);
+ }
+
+ assert(FALSE);
+ exit(255);
+}
+
+
+Bool
+Panic_GetPanicMsgPost(void)
+{
+ return FALSE;
+}
diff --git a/open-vm-tools/lib/syncDriver/syncDriverLinux.c b/open-vm-tools/lib/syncDriver/syncDriverLinux.c
index 71b841d0..6521e414 100644
--- a/open-vm-tools/lib/syncDriver/syncDriverLinux.c
+++ b/open-vm-tools/lib/syncDriver/syncDriverLinux.c
@@ -115,6 +115,11 @@ LinuxFiClose(SyncDriverHandle handle)
* If the first attempt at using the ioctl fails, assume that it doesn't exist
* and return SD_UNAVAILABLE, so that other means of freezing are tried.
*
+ * NOTE: This function performs two system calls open() and ioctl(). We have
+ * seen open() being slow with NFS mount points at times and ioctl() being
+ * slow when guest is performing significant IO. Therefore, caller should
+ * consider running this function in a separate thread.
+ *
* @param[in] paths Paths to freeze (colon-separated).
* @param[out] handle Handle to use for thawing.
*
@@ -138,7 +143,7 @@ LinuxDriver_Freeze(const char *paths,
DynBuf_Init(&fds);
- Debug(LGPFX "Freezing using Linux ioctls...\n");
+ Debug(LGPFX "Freezing %s using Linux ioctls...\n", paths);
sync = calloc(1, sizeof *sync);
if (sync == NULL) {
@@ -154,6 +159,7 @@ LinuxDriver_Freeze(const char *paths,
* the current kernel.
*/
while ((path = StrUtil_GetNextToken(&index, paths, ":")) != NULL) {
+ Debug(LGPFX "opening path '%s'.\n", path);
fd = open(path, O_RDONLY);
if (fd == -1) {
switch (errno) {
@@ -185,6 +191,7 @@ LinuxDriver_Freeze(const char *paths,
}
}
+ Debug(LGPFX "freezing path '%s'.\n", path);
if (ioctl(fd, FIFREEZE) == -1) {
int ioctlerr = errno;
/*
@@ -198,6 +205,8 @@ LinuxDriver_Freeze(const char *paths,
* bind mounts).
*/
close(fd);
+ Debug(LGPFX "freeze on '%s' returned: %d (%s)\n",
+ path, ioctlerr, strerror(ioctlerr));
if (ioctlerr != EBUSY && ioctlerr != EOPNOTSUPP) {
Debug(LGPFX "failed to freeze '%s': %d (%s)\n",
path, ioctlerr, strerror(ioctlerr));
diff --git a/open-vm-tools/lib/syncDriver/syncDriverPosix.c b/open-vm-tools/lib/syncDriver/syncDriverPosix.c
index 75431c35..a6e4e1ec 100644
--- a/open-vm-tools/lib/syncDriver/syncDriverPosix.c
+++ b/open-vm-tools/lib/syncDriver/syncDriverPosix.c
@@ -249,7 +249,9 @@ SyncDriver_Freeze(const char *userPaths, // IN
}
while (err == SD_UNAVAILABLE && i < ARRAYSIZE(gBackends)) {
- SyncFreezeFn freezeFn = gBackends[i++];
+ SyncFreezeFn freezeFn = gBackends[i];
+ Debug(LGPFX "Calling backend %d.\n", (int) i);
+ i++;
#if defined(__linux__) && !defined(USERWORLD)
if (!enableNullDriver && (freezeFn == NullDriver_Freeze)) {
Debug(LGPFX "Skipping nullDriver backend.\n");
diff --git a/open-vm-tools/lib/syncDriver/vmSyncDriver.c b/open-vm-tools/lib/syncDriver/vmSyncDriver.c
index b1c4b8a1..c0c5158f 100644
--- a/open-vm-tools/lib/syncDriver/vmSyncDriver.c
+++ b/open-vm-tools/lib/syncDriver/vmSyncDriver.c
@@ -104,7 +104,7 @@ VmSync_Freeze(const char *paths,
int file;
VmSyncDriver *sync = NULL;
- Debug(LGPFX "Freezing using vmsync driver...\n");
+ Debug(LGPFX "Freezing %s using vmsync driver...\n", paths);
file = open(SYNC_PROC_PATH, O_RDONLY);
if (file == -1) {
diff --git a/open-vm-tools/lib/system/systemLinux.c b/open-vm-tools/lib/system/systemLinux.c
index 3e453dff..559577a4 100644
--- a/open-vm-tools/lib/system/systemLinux.c
+++ b/open-vm-tools/lib/system/systemLinux.c
@@ -281,7 +281,7 @@ System_Uptime(void)
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
System_GetTimeAsString(void)
{
struct timeval tv;
@@ -290,8 +290,8 @@ System_GetTimeAsString(void)
size_t charsWritten;
size_t bufSize = 8; // Multiplied by 2 for the initial allocation.
char *buf = NULL;
- Unicode dateTime = NULL;
- Unicode output = NULL;
+ char *dateTime = NULL;
+ char *output = NULL;
if (gettimeofday(&tv, NULL)) {
goto out;
@@ -331,7 +331,7 @@ System_GetTimeAsString(void)
out:
free(buf);
- Unicode_Free(dateTime);
+ free(dateTime);
return output;
}
diff --git a/open-vm-tools/lib/unicode/unicodeCommon.c b/open-vm-tools/lib/unicode/unicodeCommon.c
index 0073b5a4..f12f666f 100644
--- a/open-vm-tools/lib/unicode/unicodeCommon.c
+++ b/open-vm-tools/lib/unicode/unicodeCommon.c
@@ -297,7 +297,7 @@ Unicode_UTF16Strdup(const utf16_t *utf16) // IN: May be NULL.
* Results:
* An allocated Unicode string containing the decoded characters
* in buffer, or NULL if input is NULL.
- * Caller must pass the string to Unicode_Free to free.
+ * Caller must pass the string to free to free.
*
* Side effects:
* None
@@ -305,12 +305,12 @@ Unicode_UTF16Strdup(const utf16_t *utf16) // IN: May be NULL.
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
Unicode_AllocWithLength(const void *buffer, // IN:
ssize_t lengthInBytes, // IN:
StringEncoding encoding) // IN:
{
- Unicode result;
+ char *result;
ASSERT(lengthInBytes >= 0 || lengthInBytes == -1);
@@ -365,7 +365,7 @@ Unicode_AllocWithLength(const void *buffer, // IN:
*/
Bool
-Unicode_CanGetBytesWithEncoding(ConstUnicode ustr, // IN:
+Unicode_CanGetBytesWithEncoding(const char *ustr, // IN:
StringEncoding encoding) // IN:
{
void *tmp;
diff --git a/open-vm-tools/lib/unicode/unicodeICU.c b/open-vm-tools/lib/unicode/unicodeICU.c
index 4cbb4a66..ca018bf8 100644
--- a/open-vm-tools/lib/unicode/unicodeICU.c
+++ b/open-vm-tools/lib/unicode/unicodeICU.c
@@ -55,8 +55,8 @@
*/
int
-Unicode_CompareWithLocale(ConstUnicode str1, // IN
- ConstUnicode str2, // IN
+Unicode_CompareWithLocale(const char *str1, // IN
+ const char *str2, // IN
const char *locale, // IN
UnicodeCompareOption compareOption) // IN
{
@@ -154,7 +154,7 @@ Unicode_CompareWithLocale(ConstUnicode str1, // IN
*
* Results:
* The allocated Unicode string, or NULL on failure.
- * Caller must free with Unicode_Free().
+ * Caller must free with free().
*
* Side effects:
* None
@@ -162,13 +162,13 @@ Unicode_CompareWithLocale(ConstUnicode str1, // IN
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_Normalize(ConstUnicode str, // IN
+char *
+Unicode_Normalize(const char *str, // IN
UnicodeNormalizationForm form) // IN
{
UNormalizationMode mode;
UChar *uchars;
- Unicode result;
+ char *result;
int32_t normalizedLen;
UErrorCode status = U_ZERO_ERROR;
UCharIterator strIter;
@@ -246,7 +246,7 @@ Unicode_Normalize(ConstUnicode str, // IN
*
* Results:
* The allocated Unicode string, or NULL on failure.
- * Caller must free with Unicode_Free().
+ * Caller must free with free().
*
* Side effects:
* None
@@ -254,8 +254,8 @@ Unicode_Normalize(ConstUnicode str, // IN
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_ToLower(ConstUnicode str, // IN
+char *
+Unicode_ToLower(const char *str, // IN
const char *locale) // IN
{
UCaseMap *caseMap;
@@ -265,7 +265,7 @@ Unicode_ToLower(ConstUnicode str, // IN
int32_t utf8SrcLen = strlen(utf8Src);
int32_t destCapacity = utf8SrcLen + 1;
int32_t destLen;
- Unicode result = NULL;
+ char *result = NULL;
/*
* XXX TODO: This and the two following functions are substantially
@@ -309,7 +309,7 @@ Unicode_ToLower(ConstUnicode str, // IN
ucasemap_close(caseMap);
if (U_SUCCESS(status) && status != U_STRING_NOT_TERMINATED_WARNING) {
- result = (Unicode)utf8Dest;
+ result = utf8Dest;
} else {
ASSERT(U_SUCCESS(status));
ASSERT(status != U_STRING_NOT_TERMINATED_WARNING);
@@ -334,7 +334,7 @@ Unicode_ToLower(ConstUnicode str, // IN
*
* Results:
* The allocated Unicode string, or NULL on failure.
- * Caller must free with Unicode_Free().
+ * Caller must free with free().
*
* Side effects:
* None
@@ -342,8 +342,8 @@ Unicode_ToLower(ConstUnicode str, // IN
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_ToUpper(ConstUnicode str, // IN
+char *
+Unicode_ToUpper(const char *str, // IN
const char *locale) // IN
{
UCaseMap *caseMap;
@@ -353,7 +353,7 @@ Unicode_ToUpper(ConstUnicode str, // IN
int32_t utf8SrcLen = strlen(utf8Src);
int32_t destCapacity = utf8SrcLen + 1;
int32_t destLen;
- Unicode result = NULL;
+ char *result = NULL;
// Most upper-case operations don't change the length of the string.
utf8Dest = (char *)Util_SafeMalloc(destCapacity);
@@ -390,7 +390,7 @@ Unicode_ToUpper(ConstUnicode str, // IN
ucasemap_close(caseMap);
if (U_SUCCESS(status) && status != U_STRING_NOT_TERMINATED_WARNING) {
- result = (Unicode)utf8Dest;
+ result = utf8Dest;
} else {
ASSERT(U_SUCCESS(status));
ASSERT(status != U_STRING_NOT_TERMINATED_WARNING);
@@ -425,7 +425,7 @@ Unicode_ToUpper(ConstUnicode str, // IN
*
* Results:
* The allocated Unicode string, or NULL on failure.
- * Caller must free with Unicode_Free().
+ * Caller must free with free().
*
* Side effects:
* None
@@ -433,8 +433,8 @@ Unicode_ToUpper(ConstUnicode str, // IN
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_ToTitle(ConstUnicode str, // IN
+char *
+Unicode_ToTitle(const char *str, // IN
const char *locale) // IN
{
UCaseMap *caseMap;
@@ -444,7 +444,7 @@ Unicode_ToTitle(ConstUnicode str, // IN
int32_t utf8SrcLen = strlen(utf8Src);
int32_t destCapacity = utf8SrcLen + 1;
int32_t destLen;
- Unicode result = NULL;
+ char *result = NULL;
// Most title-case operations don't change the length of the string.
utf8Dest = (char *)Util_SafeMalloc(destCapacity);
@@ -481,7 +481,7 @@ Unicode_ToTitle(ConstUnicode str, // IN
ucasemap_close(caseMap);
if (U_SUCCESS(status) && status != U_STRING_NOT_TERMINATED_WARNING) {
- result = (Unicode)utf8Dest;
+ result = utf8Dest;
} else {
ASSERT(U_SUCCESS(status));
ASSERT(status != U_STRING_NOT_TERMINATED_WARNING);
diff --git a/open-vm-tools/lib/unicode/unicodeInt.h b/open-vm-tools/lib/unicode/unicodeInt.h
index cd65aedd..1774eb3b 100644
--- a/open-vm-tools/lib/unicode/unicodeInt.h
+++ b/open-vm-tools/lib/unicode/unicodeInt.h
@@ -32,17 +32,17 @@
extern "C" {
#endif
-Unicode UnicodeAllocInternal(const void *buffer,
- ssize_t lengthInBytes,
- StringEncoding encoding,
- Bool strict);
+char *UnicodeAllocInternal(const void *buffer,
+ ssize_t lengthInBytes,
+ StringEncoding encoding,
+ Bool strict);
-Unicode UnicodeAllocStatic(const char *asciiBytes,
- Bool unescape);
+char *UnicodeAllocStatic(const char *asciiBytes,
+ Bool unescape);
utf16_t UnicodeSimpleCaseFold(utf16_t codeUnit);
-void *UnicodeGetAllocBytesInternal(ConstUnicode src,
+void *UnicodeGetAllocBytesInternal(const char *src,
StringEncoding encoding,
ssize_t lengthInBytes,
size_t *retLength);
diff --git a/open-vm-tools/lib/unicode/unicodeSimpleBase.c b/open-vm-tools/lib/unicode/unicodeSimpleBase.c
index 70f47158..5f99c00e 100644
--- a/open-vm-tools/lib/unicode/unicodeSimpleBase.c
+++ b/open-vm-tools/lib/unicode/unicodeSimpleBase.c
@@ -25,13 +25,13 @@
*
* Basic Unicode string creation and encoding conversion.
*
- * The thread-safety of ConstUnicode functions is the same as
+ * The thread-safety of const char *functions is the same as
* that for standard const char * functions: multiple threads can
- * call ConstUnicode functions on the same string simultaneously.
+ * call const char *functions on the same string simultaneously.
*
- * However, a non-const Unicode function (like Unicode_Free) must
+ * However, a non-const Unicode function (like free) must
* not be called concurrently with any other Unicode or
- * ConstUnicode function on the same string.
+ * const char *function on the same string.
*/
#include <string.h>
@@ -78,7 +78,7 @@ static const size_t UNICODE_UTF16_CODE_UNITS_PADDING = 10;
* Results:
* An allocated Unicode string containing the decoded characters
* in buffer, or NULL on failure. Caller must pass to
- * Unicode_Free to free.
+ * free to free.
*
* Side effects:
* None
@@ -86,7 +86,7 @@ static const size_t UNICODE_UTF16_CODE_UNITS_PADDING = 10;
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
UnicodeAllocInternal(const void *buffer, // IN
ssize_t lengthInBytes, // IN
StringEncoding encoding, // IN
@@ -126,7 +126,7 @@ UnicodeAllocInternal(const void *buffer, // IN
break;
}
- return (Unicode)utf8Result;
+ return utf8Result;
}
@@ -192,7 +192,7 @@ Unicode_IsBufferValid(const void *buffer, // IN
*
* Results:
* An allocated Unicode string containing a duplicate of the passed-in
- * string. Caller must pass to Unicode_Free to free.
+ * string. Caller must pass to free to free.
*
* Side effects:
* None
@@ -200,36 +200,10 @@ Unicode_IsBufferValid(const void *buffer, // IN
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_Duplicate(ConstUnicode str) // IN
+char *
+Unicode_Duplicate(const char *str) // IN
{
- return (Unicode)Util_SafeStrdup((const char *)str);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Unicode_Free --
- *
- * Frees the memory for the specified Unicode string and invalidates it.
- *
- * Not thread-safe when other functions are concurrently
- * operating on the same string.
- *
- * Results:
- * None
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-Unicode_Free(void *str) // IN
-{
- free(str);
+ return Util_SafeStrdup(str);
}
@@ -245,8 +219,8 @@ Unicode_Free(void *str) // IN
*
* Results:
* An allocated list (vector) of Unicode strings.
- * The individual strings must be freed with Unicode_Free,
- * or the entire list can be free with Unicode_FreeList.
+ * The individual strings must be freed with free,
+ * or the entire list can be free with Util_FreeStringList.
*
* Side effects:
* None
@@ -254,12 +228,12 @@ Unicode_Free(void *str) // IN
*-----------------------------------------------------------------------------
*/
-Unicode *
+char **
Unicode_AllocList(char **srcList, // IN: list of strings
ssize_t length, // IN: list
StringEncoding encoding) // IN:
{
- Unicode *dstList = NULL;
+ char **dstList = NULL;
ssize_t i;
ASSERT(srcList != NULL);
@@ -289,34 +263,6 @@ Unicode_AllocList(char **srcList, // IN: list of strings
/*
*-----------------------------------------------------------------------------
*
- * Unicode_FreeList --
- *
- * Free a list (actually a vector) of Unicode strings.
- * The list (vector) itself is also freed.
- *
- * The list either has a specified length or is
- * argv-style NULL terminated (if length is negative).
- *
- * Results:
- * None
- *
- * Side effects:
- * errno or Windows last error is preserved.
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-Unicode_FreeList(Unicode *list, // IN: the list to free
- ssize_t length) // IN: the length
-{
- Util_FreeStringList(list, length);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
* Unicode_GetAllocList --
*
* Given a list of Unicode strings, converts them to a list of
@@ -339,9 +285,9 @@ Unicode_FreeList(Unicode *list, // IN: the list to free
*/
char **
-Unicode_GetAllocList(Unicode const srcList[], // IN: list of strings
- ssize_t length, // IN: length (-1 for NULL term.)
- StringEncoding encoding) // IN: Encoding of returned list
+Unicode_GetAllocList(char *const srcList[], // IN: list of strings
+ ssize_t length, // IN: length (-1 for NULL term.)
+ StringEncoding encoding) // IN: Encoding of returned list
{
char **dstList = NULL;
ssize_t i;
@@ -380,35 +326,6 @@ Unicode_GetAllocList(Unicode const srcList[], // IN: list of strings
/*
*-----------------------------------------------------------------------------
*
- * Unicode_GetUTF8 --
- *
- * Returns the contents of the string encoded as a NUL-terminated UTF-8
- * byte array.
- *
- * Results:
- * A NUL-terminated UTF-8 string; lifetime is valid until the next
- * non-const Unicode function is called on the string. Caller should
- * strdup if storing the return value long-term.
- *
- * Caller does not need to free; the memory is managed inside the
- * Unicode object.
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-const char *
-Unicode_GetUTF8(ConstUnicode str) // IN
-{
- return (const char *)str;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
* Unicode_LengthInCodeUnits --
*
* Gets the length of the Unicode string in UTF-8 code units.
@@ -423,7 +340,7 @@ Unicode_GetUTF8(ConstUnicode str) // IN
*/
UnicodeIndex
-Unicode_LengthInCodeUnits(ConstUnicode str) // IN
+Unicode_LengthInCodeUnits(const char *str) // IN
{
return strlen((const char *)str);
}
@@ -451,7 +368,7 @@ Unicode_LengthInCodeUnits(ConstUnicode str) // IN
*/
size_t
-Unicode_BytesRequired(ConstUnicode str, // IN
+Unicode_BytesRequired(const char *str, // IN
StringEncoding encoding) // IN
{
const uint8 *utf8 = (const uint8 *)str;
@@ -566,7 +483,7 @@ Unicode_BytesRequired(ConstUnicode str, // IN
Bool
Unicode_CopyBytes(void *destBuffer, // OUT
- ConstUnicode srcBuffer, // IN
+ const char *srcBuffer, // IN
size_t maxLengthInBytes, // IN
size_t *retLength, // OUT
StringEncoding encoding) // IN
@@ -695,7 +612,7 @@ Unicode_CopyBytes(void *destBuffer, // OUT
*/
void *
-Unicode_GetAllocBytes(ConstUnicode str, // IN:
+Unicode_GetAllocBytes(const char *str, // IN:
StringEncoding encoding) // IN:
{
if (str == NULL) {
@@ -735,7 +652,7 @@ Unicode_GetAllocBytes(ConstUnicode str, // IN:
*/
void *
-Unicode_GetAllocBytesWithLength(ConstUnicode str, // IN:
+Unicode_GetAllocBytesWithLength(const char *str, // IN:
StringEncoding encoding, // IN:
ssize_t lengthInBytes) // IN:
{
@@ -770,7 +687,7 @@ Unicode_GetAllocBytesWithLength(ConstUnicode str, // IN:
*/
void *
-UnicodeGetAllocBytesInternal(ConstUnicode ustr, // IN
+UnicodeGetAllocBytesInternal(const char *ustr, // IN
StringEncoding encoding, // IN
ssize_t lengthInBytes, // IN
size_t *retLength) // OUT: optional
@@ -841,7 +758,7 @@ UnicodeGetAllocBytesInternal(ConstUnicode ustr, // IN
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
UnicodeAllocStatic(const char *asciiBytes, // IN
Bool unescape) // IN
{
@@ -849,7 +766,7 @@ UnicodeAllocStatic(const char *asciiBytes, // IN
// Explicitly use int8 so we don't depend on whether char is signed.
const int8 *byte = (const int8 *)asciiBytes;
size_t utf16Offset = 0;
- Unicode result;
+ char *result;
ASSERT(asciiBytes);
diff --git a/open-vm-tools/lib/unicode/unicodeSimpleCaseFolding.c b/open-vm-tools/lib/unicode/unicodeSimpleCaseFolding.c
index db1f08bb..9ca294c7 100644
--- a/open-vm-tools/lib/unicode/unicodeSimpleCaseFolding.c
+++ b/open-vm-tools/lib/unicode/unicodeSimpleCaseFolding.c
@@ -1,5 +1,5 @@
/* **********************************************************
- * Copyright 2007 VMware, Inc. All rights reserved.
+ * Copyright 2007-2014 VMware, Inc. All rights reserved.
* **********************************************************/
/*
diff --git a/open-vm-tools/lib/unicode/unicodeSimpleOperations.c b/open-vm-tools/lib/unicode/unicodeSimpleOperations.c
index 33c5bcbd..eae5a929 100644
--- a/open-vm-tools/lib/unicode/unicodeSimpleOperations.c
+++ b/open-vm-tools/lib/unicode/unicodeSimpleOperations.c
@@ -50,7 +50,7 @@
*/
UnicodeIndex
-Unicode_LengthInCodePoints(ConstUnicode str) // IN:
+Unicode_LengthInCodePoints(const char *str) // IN:
{
return CodeSet_LengthInCodePoints(str);
}
@@ -94,17 +94,17 @@ Unicode_LengthInCodePoints(ConstUnicode str) // IN:
*/
int
-Unicode_CompareRange(ConstUnicode str1, // IN:
+Unicode_CompareRange(const char *str1, // IN:
UnicodeIndex str1Start, // IN:
UnicodeIndex str1Length, // IN:
- ConstUnicode str2, // IN:
+ const char *str2, // IN:
UnicodeIndex str2Start, // IN:
UnicodeIndex str2Length, // IN:
Bool ignoreCase) // IN:
{
int result = -1;
- Unicode substr1 = NULL;
- Unicode substr2 = NULL;
+ char *substr1 = NULL;
+ char *substr2 = NULL;
utf16_t *substr1UTF16 = NULL;
utf16_t *substr2UTF16 = NULL;
UnicodeIndex i = 0;
@@ -220,8 +220,8 @@ Unicode_CompareRange(ConstUnicode str1, // IN:
free(substr1UTF16);
free(substr2UTF16);
- Unicode_Free(substr1);
- Unicode_Free(substr2);
+ free(substr1);
+ free(substr2);
return result;
}
@@ -258,10 +258,10 @@ Unicode_CompareRange(ConstUnicode str1, // IN:
*/
UnicodeIndex
-Unicode_FindSubstrInRange(ConstUnicode str, // IN:
+Unicode_FindSubstrInRange(const char *str, // IN:
UnicodeIndex strStart, // IN:
UnicodeIndex strLength, // IN:
- ConstUnicode strToFind, // IN:
+ const char *strToFind, // IN:
UnicodeIndex strToFindStart, // IN:
UnicodeIndex strToFindLength) // IN:
{
@@ -383,10 +383,10 @@ bail:
*/
UnicodeIndex
-Unicode_FindLastSubstrInRange(ConstUnicode str, // IN:
+Unicode_FindLastSubstrInRange(const char *str, // IN:
UnicodeIndex strStart, // IN:
UnicodeIndex strLength, // IN:
- ConstUnicode strToFind, // IN:
+ const char *strToFind, // IN:
UnicodeIndex strToFindStart, // IN:
UnicodeIndex strToFindLength) // IN:
{
@@ -495,7 +495,7 @@ bail:
*
* Results:
* The newly-allocated substring of 'str' in the range [index,
- * index + length). Caller must free with Unicode_Free.
+ * index + length). Caller must free with free.
*
* Side effects:
* None
@@ -503,8 +503,8 @@ bail:
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_Substr(ConstUnicode str, // IN:
+char *
+Unicode_Substr(const char *str, // IN:
UnicodeIndex start, // IN:
UnicodeIndex length) // IN:
{
@@ -566,7 +566,7 @@ Unicode_Substr(ConstUnicode str, // IN:
*
* Results:
* A newly-allocated string containing the results of the replace
- * operation. Caller must free with Unicode_Free.
+ * operation. Caller must free with free.
*
* Side effects:
* None
@@ -574,18 +574,18 @@ Unicode_Substr(ConstUnicode str, // IN:
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_ReplaceRange(ConstUnicode dest, // IN:
+char *
+Unicode_ReplaceRange(const char *dest, // IN:
UnicodeIndex destStart, // IN:
UnicodeIndex destLength, // IN:
- ConstUnicode src, // IN:
+ const char *src, // IN:
UnicodeIndex srcStart, // IN:
UnicodeIndex srcLength) // IN:
{
- Unicode result;
- Unicode stringOne;
- Unicode stringTwo;
- Unicode stringThree;
+ char *result;
+ char *stringOne;
+ char *stringTwo;
+ char *stringThree;
ASSERT(dest);
ASSERT((destStart >= 0) || (destStart == -1));
@@ -601,9 +601,9 @@ Unicode_ReplaceRange(ConstUnicode dest, // IN:
result = Unicode_Join(stringOne, stringTwo, stringThree, NULL);
- Unicode_Free(stringOne);
- Unicode_Free(stringTwo);
- Unicode_Free(stringThree);
+ free(stringOne);
+ free(stringTwo);
+ free(stringThree);
return result;
}
@@ -615,12 +615,11 @@ Unicode_ReplaceRange(ConstUnicode dest, // IN:
* Unicode_Join --
*
* Allocates and returns a new string containing the 'first' followed by
- * all the unicode strings specified as optional arguments (which must
- * be of type ConstUnicode). Appending ceases when a NULL pointer is
- * detected.
+ * all the unicode strings specified as optional arguments. Appending
+ * ceases when a NULL pointer is detected.
*
* Results:
- * The newly-allocated string. Caller must free with Unicode_Free.
+ * The newly-allocated string. Caller must free with free.
*
* Side effects:
* None
@@ -628,27 +627,27 @@ Unicode_ReplaceRange(ConstUnicode dest, // IN:
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_Join(ConstUnicode first, // IN:
- ...) // IN:
+char *
+Unicode_Join(const char *first, // IN:
+ ...) // IN:
{
- Unicode result;
+ char *result;
if (first == NULL) {
result = NULL;
} else {
va_list args;
- ConstUnicode cur;
+ const char *cur;
result = Unicode_Duplicate(first);
va_start(args, first);
- while ((cur = va_arg(args, ConstUnicode)) != NULL) {
- Unicode temp;
+ while ((cur = va_arg(args, const char *)) != NULL) {
+ char *temp;
temp = Unicode_Format("%s%s", result, cur);
- Unicode_Free(result);
+ free(result);
result = temp;
}
@@ -675,7 +674,7 @@ Unicode_Join(ConstUnicode first, // IN:
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
Unicode_Format(const char *fmt, // IN: the format
...) // IN: the arguments
{
diff --git a/open-vm-tools/lib/unicode/unicodeSimpleTransforms.c b/open-vm-tools/lib/unicode/unicodeSimpleTransforms.c
index 6136fda9..77b22c0a 100644
--- a/open-vm-tools/lib/unicode/unicodeSimpleTransforms.c
+++ b/open-vm-tools/lib/unicode/unicodeSimpleTransforms.c
@@ -305,7 +305,7 @@ UnicodeSimpleIsWhiteSpace(utf16_t codeUnit) // IN
* input string.
*
* Results:
- * The allocated Unicode string. Caller must free with Unicode_Free().
+ * The allocated Unicode string. Caller must free with free().
*
* Side effects:
* None
@@ -313,10 +313,10 @@ UnicodeSimpleIsWhiteSpace(utf16_t codeUnit) // IN
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_FoldCase(ConstUnicode str) // IN
+char *
+Unicode_FoldCase(const char *str) // IN
{
- Unicode folded;
+ char *folded;
utf16_t *utf16;
utf16_t *utf16Current;
@@ -346,7 +346,7 @@ Unicode_FoldCase(ConstUnicode str) // IN
* and/or end of the input string, depending on the input parameter "side".
*
* Results:
- * The allocated Unicode string. Caller must free with Unicode_Free().
+ * The allocated Unicode string. Caller must free with free().
*
* Side effects:
* None
@@ -354,11 +354,11 @@ Unicode_FoldCase(ConstUnicode str) // IN
*-----------------------------------------------------------------------------
*/
-static Unicode
-UnicodeTrimInternal(ConstUnicode str, // IN
+static char *
+UnicodeTrimInternal(const char *str, // IN
UnicodeTrimSide side) // IN
{
- Unicode trimmed;
+ char *trimmed;
utf16_t *utf16;
utf16_t *utf16Start;
utf16_t *utf16End;
@@ -399,7 +399,7 @@ UnicodeTrimInternal(ConstUnicode str, // IN
* and end of the input string.
*
* Results:
- * The allocated Unicode string. Caller must free with Unicode_Free().
+ * The allocated Unicode string. Caller must free with free().
*
* Side effects:
* None
@@ -407,8 +407,8 @@ UnicodeTrimInternal(ConstUnicode str, // IN
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_Trim(ConstUnicode str) // IN
+char *
+Unicode_Trim(const char *str) // IN
{
return UnicodeTrimInternal(str, UNICODE_TRIMBOTH);
}
@@ -419,11 +419,11 @@ Unicode_Trim(ConstUnicode str) // IN
*
* Unicode_TrimLeft --
*
- * Creates a Unicode string by trimming whitespace from the beginning of the
- * input string.
+ * Creates a Unicode string by trimming whitespace from the beginning of
+ * the input string.
*
* Results:
- * The allocated Unicode string. Caller must free with Unicode_Free().
+ * The allocated Unicode string. Caller must free with free().
*
* Side effects:
* None
@@ -431,8 +431,8 @@ Unicode_Trim(ConstUnicode str) // IN
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_TrimLeft(ConstUnicode str) // IN
+char *
+Unicode_TrimLeft(const char *str) // IN
{
return UnicodeTrimInternal(str, UNICODE_TRIMLEFT);
}
@@ -447,7 +447,7 @@ Unicode_TrimLeft(ConstUnicode str) // IN
* input string.
*
* Results:
- * The allocated Unicode string. Caller must free with Unicode_Free().
+ * The allocated Unicode string. Caller must free with free().
*
* Side effects:
* None
@@ -455,8 +455,8 @@ Unicode_TrimLeft(ConstUnicode str) // IN
*-----------------------------------------------------------------------------
*/
-Unicode
-Unicode_TrimRight(ConstUnicode str) // IN
+char *
+Unicode_TrimRight(const char *str) // IN
{
return UnicodeTrimInternal(str, UNICODE_TRIMRIGHT);
}
diff --git a/open-vm-tools/lib/unicode/unicodeStatic.c b/open-vm-tools/lib/unicode/unicodeStatic.c
index 9f0c6cf3..b9d2a81a 100644
--- a/open-vm-tools/lib/unicode/unicodeStatic.c
+++ b/open-vm-tools/lib/unicode/unicodeStatic.c
@@ -19,13 +19,13 @@
/*
* unicodeStatic.c --
*
- * Manages memory for static ConstUnicode literal strings
+ * Manages memory for static const char *literal strings
* created like:
*
- * ConstUnicode c = U_UNESCAPE("Copyright \\u00A9 VMware, Inc.");
+ * const char *c = U_UNESCAPE("Copyright \\u00A9 VMware, Inc.");
*
- * Uses two HashTables to hold static ConstUnicode strings. Static
- * ConstUnicode strings are keyed off the ASCII bytes passed to the
+ * Uses two HashTables to hold static const char *strings. Static
+ * const char *strings are keyed off the ASCII bytes passed to the
* static macros.
*
* Unescaped strings are kept separate from escaped strings so
@@ -75,7 +75,7 @@ static Atomic_Ptr UnicodeUnescapedStringTable;
static void
UnicodeHashFree(void *v) // IN:
{
- Unicode_Free((Unicode) v);
+ free(v);
}
@@ -86,7 +86,7 @@ UnicodeHashFree(void *v) // IN:
*
* Helper function for the U_UNESCAPE() macro.
*
- * Given a NUL-terminated ASCII string, returns a ConstUnicode
+ * Given a NUL-terminated ASCII string, returns a const char *
* string containing the string's contents.
*
* If unescape is TRUE, then \\uABCD becomes the Unicode code
@@ -94,7 +94,7 @@ UnicodeHashFree(void *v) // IN:
* U+1FABCD in the resulting string.
*
* Results:
- * A ConstUnicode string. Memory is managed inside this module;
+ * A const char * string. Memory is managed inside this module;
* caller does not need to free.
*
* Side effects:
@@ -106,11 +106,11 @@ UnicodeHashFree(void *v) // IN:
*-----------------------------------------------------------------------------
*/
-ConstUnicode
+const char *
Unicode_GetStatic(const char *asciiBytes, // IN
Bool unescape) // IN
{
- Unicode result = NULL;
+ char *result = NULL;
HashTable *stringTable;
if (unescape) {
@@ -134,13 +134,13 @@ Unicode_GetStatic(const char *asciiBytes, // IN
*/
if (!HashTable_Lookup(stringTable, asciiBytes, (void **) &result)) {
- Unicode newData = UnicodeAllocStatic(asciiBytes, unescape);
+ char *newData = UnicodeAllocStatic(asciiBytes, unescape);
if (newData) {
result = HashTable_LookupOrInsert(stringTable, asciiBytes, newData);
if (result != newData) {
- Unicode_Free(newData);
+ free(newData);
}
}
}
diff --git a/open-vm-tools/lib/user/util.c b/open-vm-tools/lib/user/util.c
index 98b86f04..f320635e 100644
--- a/open-vm-tools/lib/user/util.c
+++ b/open-vm-tools/lib/user/util.c
@@ -93,7 +93,7 @@ struct UtilVector {
*
* Util_Init --
*
- * Opportunity to sanity check things
+ * Opportunity to sanity check things
*
* Results:
* Bool - TRUE (this should never fail)
@@ -117,11 +117,11 @@ Util_Init(void)
char buf[2] = { 'x', 'x' };
int rv;
- rv = Str_Snprintf(buf, sizeof(buf), "a");
+ rv = Str_Snprintf(buf, sizeof buf, "a");
ASSERT(rv == 1);
ASSERT(!strcmp(buf, "a"));
- rv = Str_Snprintf(buf, sizeof(buf), "ab");
+ rv = Str_Snprintf(buf, sizeof buf, "ab");
ASSERT(rv == -1);
ASSERT(!strcmp(buf, "a"));
}
@@ -437,7 +437,9 @@ int
Util_GetOpt(int argc, // IN
char * const *argv, // IN
const struct option *opts, // IN
- Util_NonOptMode mode) // IN
+ Util_NonOptMode mode, // IN
+ Bool manualErrorHandling) // IN: True if the caller wants to handle error reporting.
+
{
int ret = -1;
@@ -449,7 +451,7 @@ Util_GetOpt(int argc, // IN
* an optional argument.
*/
const size_t maxCharsPerShortOption = 3;
- const size_t modePrefixSize = 1;
+ const size_t modePrefixSize = 2; // "[+-][:]"
size_t n = 0;
size_t shortOptStringSize;
@@ -493,6 +495,7 @@ Util_GetOpt(int argc, // IN
struct option *longOptOut = longOpts;
char *shortOptOut = shortOptString;
+ // How to handle non-option arguments.
switch (mode) {
case UTIL_NONOPT_STOP:
*shortOptOut++ = '+';
@@ -504,6 +507,14 @@ Util_GetOpt(int argc, // IN
break;
}
+ if (manualErrorHandling) {
+ /*
+ * Make getopt return ':' instead of '?' if required arguments to
+ * options are missing.
+ */
+ *shortOptOut++ = ':';
+ }
+
for (i = 0; i < n; i++) {
int val = opts[i].val;
@@ -663,14 +674,13 @@ Util_DeriveFileName(const char *source, // IN: path to dict file (incl filename)
if (!Util_IsAbsolutePath(name) && strlen(path) > 0 &&
strcmp(path, ".") != 0) {
if (ext == NULL) {
- returnResult = Str_Asprintf(NULL, "%s%s%s",
- path, DIRSEPS, name);
+ returnResult = Str_SafeAsprintf(NULL, "%s%s%s",
+ path, DIRSEPS, name);
} else {
- returnResult = Str_Asprintf(NULL, "%s%s%s.%s",
- path, DIRSEPS, name, ext);
+ returnResult = Str_SafeAsprintf(NULL, "%s%s%s.%s",
+ path, DIRSEPS, name, ext);
}
} else {
-
/*
* Path is non-existent or is just the current directory (or the
* result from the dictionary is an absolute path), so we
@@ -680,9 +690,9 @@ Util_DeriveFileName(const char *source, // IN: path to dict file (incl filename)
*/
if (ext == NULL) {
- returnResult = Str_Asprintf(NULL, "%s", name);
+ returnResult = Util_SafeStrdup(name);
} else {
- returnResult = Str_Asprintf(NULL, "%s.%s", name, ext);
+ returnResult = Str_SafeAsprintf(NULL, "%s.%s", name, ext);
}
}
free(path);
@@ -701,16 +711,15 @@ Util_DeriveFileName(const char *source, // IN: path to dict file (incl filename)
/* Combine disk path with parent path */
if (strlen(path) > 0 && strcmp(path, ".") != 0) {
- returnResult = Str_Asprintf(NULL, "%s%s%s.%s",
- path, DIRSEPS, base, ext);
+ returnResult = Str_SafeAsprintf(NULL, "%s%s%s.%s",
+ path, DIRSEPS, base, ext);
} else {
-
/*
* Path is non-existent or is just the current directory, so we
* just need to use the filename (using the DIRSEPS method might
* result in something undesireable like "\foobar.vmdk")
*/
- returnResult = Str_Asprintf(NULL, "%s.%s", base, ext);
+ returnResult = Str_SafeAsprintf(NULL, "%s.%s", base, ext);
}
free(path);
free(base);
diff --git a/open-vm-tools/lib/user/utilBacktrace.c b/open-vm-tools/lib/user/utilBacktrace.c
index ba446d32..8475a2e3 100644
--- a/open-vm-tools/lib/user/utilBacktrace.c
+++ b/open-vm-tools/lib/user/utilBacktrace.c
@@ -504,18 +504,19 @@ Util_BacktraceWithFunc(int bugNr, // IN:
Util_OutputFunc outFunc, // IN:
void *outFuncData) // IN:
{
-#if !defined(_WIN32)
+#if defined(_WIN32)
+ CoreDumpFullBacktraceOptions options = {0};
+
+ options.bugNumber = bugNr;
+ CoreDump_LogFullBacktraceToFunc(&options, outFunc, outFuncData);
+#else
uintptr_t *x = (uintptr_t *) &bugNr;
-#endif
if (bugNr == 0) {
outFunc(outFuncData, "Backtrace:\n");
} else {
outFunc(outFuncData, "Backtrace for bugNr=%d\n",bugNr);
}
-#if defined(_WIN32)
- CoreDump_Backtrace(outFunc, outFuncData);
-#else
Util_BacktraceFromPointerWithFunc(&x[-2], outFunc, outFuncData);
#endif
}
diff --git a/open-vm-tools/lib/wiper/wiperPosix.c b/open-vm-tools/lib/wiper/wiperPosix.c
index 7eae1c5c..b216bba4 100644
--- a/open-vm-tools/lib/wiper/wiperPosix.c
+++ b/open-vm-tools/lib/wiper/wiperPosix.c
@@ -881,7 +881,7 @@ Wiper_Next(Wiper_State **s, // IN/OUT
FILEIO_OPEN_ACCESS_WRITE
| FILEIO_OPEN_DELETE_ASAP,
FILEIO_OPEN_CREATE_SAFE);
- if (fret == FILEIO_SUCCESS) {
+ if (FileIO_IsSuccess(fret)) {
break;
}
@@ -922,8 +922,7 @@ Wiper_Next(Wiper_State **s, // IN/OUT
/*
* We distiguish errors from FilieIO_Write.
*/
- if (fret != FILEIO_SUCCESS) {
-
+ if (!FileIO_IsSuccess(fret)) {
/* The file is too big even though its size is less than 2GB */
if (fret == FILEIO_WRITE_ERROR_FBIG) {
(*state)->phase = WIPER_PHASE_CREATE;
diff --git a/open-vm-tools/libhgfs/Makefile.am b/open-vm-tools/libhgfs/Makefile.am
index b4f78e8a..fb0b0834 100644
--- a/open-vm-tools/libhgfs/Makefile.am
+++ b/open-vm-tools/libhgfs/Makefile.am
@@ -21,6 +21,9 @@ libhgfs_la_LIBADD =
libhgfs_la_LIBADD += ../lib/hgfs/libHgfs.la
libhgfs_la_LIBADD += ../lib/hgfsHelper/libHgfsHelper.la
libhgfs_la_LIBADD += ../lib/hgfsServer/libHgfsServer.la
+if HAVE_GTKMM
+libhgfs_la_LIBADD += ../lib/hgfsUri/libHgfsUri.la
+endif
libhgfs_la_LIBADD += ../lib/hgfsServerManagerGuest/libHgfsServerManagerGuest.la
libhgfs_la_LIBADD += ../lib/hgfsServerPolicyGuest/libHgfsServerPolicyGuest.la
libhgfs_la_LIBADD += @GLIB2_LIBS@
diff --git a/open-vm-tools/libhgfs/Makefile.in b/open-vm-tools/libhgfs/Makefile.in
index 81ce531b..bb1d60f6 100644
--- a/open-vm-tools/libhgfs/Makefile.in
+++ b/open-vm-tools/libhgfs/Makefile.in
@@ -49,6 +49,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
+@HAVE_GTKMM_TRUE@am__append_1 = ../lib/hgfsUri/libHgfsUri.la
subdir = libhgfs
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in COPYING
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -71,7 +72,7 @@ libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES)
libhgfs_la_DEPENDENCIES = ../lib/hgfs/libHgfs.la \
../lib/hgfsHelper/libHgfsHelper.la \
- ../lib/hgfsServer/libHgfsServer.la \
+ ../lib/hgfsServer/libHgfsServer.la $(am__append_1) \
../lib/hgfsServerManagerGuest/libHgfsServerManagerGuest.la \
../lib/hgfsServerPolicyGuest/libHgfsServerPolicyGuest.la
am_libhgfs_la_OBJECTS = libhgfs_la-hgfslib.lo
@@ -287,7 +288,7 @@ top_srcdir = @top_srcdir@
lib_LTLIBRARIES = libhgfs.la
libhgfs_la_LIBADD = ../lib/hgfs/libHgfs.la \
../lib/hgfsHelper/libHgfsHelper.la \
- ../lib/hgfsServer/libHgfsServer.la \
+ ../lib/hgfsServer/libHgfsServer.la $(am__append_1) \
../lib/hgfsServerManagerGuest/libHgfsServerManagerGuest.la \
../lib/hgfsServerPolicyGuest/libHgfsServerPolicyGuest.la \
@GLIB2_LIBS@ @GTHREAD_LIBS@ @VMTOOLS_LIBS@ $(am__empty)
diff --git a/open-vm-tools/libvmtools/vmtoolsConfig.c b/open-vm-tools/libvmtools/vmtoolsConfig.c
index 50979992..6b1472f0 100644
--- a/open-vm-tools/libvmtools/vmtoolsConfig.c
+++ b/open-vm-tools/libvmtools/vmtoolsConfig.c
@@ -221,7 +221,6 @@ VMToolsConfigUpgrade(GHashTable *old,
{ CONFNAME_DISABLEPMTIMERWARNING, "desktopevents", CONFNAME_DISABLEPMTIMERWARNING, CFG_BOOLEAN, NULL },
#endif
/* Unity options. */
- { "unity.debug", CONFGROUPNAME_UNITY, CONFNAME_UNITY_ENABLEDEBUG, CFG_BOOLEAN, NULL },
{ "unity.forceEnable", CONFGROUPNAME_UNITY, CONFNAME_UNITY_FORCEENABLE, CFG_BOOLEAN, NULL },
{ "unity.desktop.backgroundColor", CONFGROUPNAME_UNITY, CONFNAME_UNITY_BACKGROUNDCOLOR, CFG_INTEGER, NULL },
/* Null terminator. */
@@ -334,6 +333,7 @@ VMTools_LoadConfig(const gchar *path,
GHashTable *old = NULL;
GError *err = NULL;
GKeyFile *cfg = NULL;
+ static gboolean hadConfFile = TRUE;
g_return_val_if_fail(config != NULL, FALSE);
@@ -358,11 +358,20 @@ VMTools_LoadConfig(const gchar *path,
g_warning("Failed to stat conf file: %s\n", strerror(errno));
goto exit;
} else {
- cfg = g_key_file_new();
+ /*
+ * If we used to have a file, create a config.
+ * Otherwise we can re-use the empty GKeyFile from before.
+ */
+ if (hadConfFile) {
+ cfg = g_key_file_new();
+ }
+ hadConfFile = FALSE;
goto exit;
}
}
+ hadConfFile = TRUE;
+
/* Check if we really need to load the data. */
if (mtime != NULL && confStat.st_mtime <= *mtime) {
goto exit;
diff --git a/open-vm-tools/libvmtools/vmtoolsLog.c b/open-vm-tools/libvmtools/vmtoolsLog.c
index 2ef66f9f..d281e89d 100644
--- a/open-vm-tools/libvmtools/vmtoolsLog.c
+++ b/open-vm-tools/libvmtools/vmtoolsLog.c
@@ -26,6 +26,9 @@
*
* To choose the logging domain for your source file, define G_LOG_DOMAIN
* before including glib.h.
+ *
+ * All fatal error messages will go to the 'syslog' handler no
+ * matter what handler has been configured.
*/
#include "vmtoolsInt.h"
@@ -46,16 +49,35 @@
# include <dbghelp.h>
# include "coreDump.h"
# include "w32Messages.h"
+# include "win32u.h"
#endif
#include "str.h"
#include "system.h"
+#include "vmware/tools/log.h"
#define LOGGING_GROUP "logging"
-#define MAX_DOMAIN_LEN 64
+#define MAX_DOMAIN_LEN (64)
+
+/*
+ * Default max number of log messages to be cached when log IO
+ * has been frozen. In case of cache overflow, only the most
+ * recent messages are preserved.
+ */
+#define DEFAULT_MAX_CACHE_ENTRIES (4*1024)
/** The default handler to use if none is specified by the config data. */
-#define DEFAULT_HANDLER "syslog"
+#define DEFAULT_HANDLER "file+"
+
+/** The default logfile location. */
+#ifdef WIN32
+// Windows log goes to %windir%\temp\vmware-<service>.log
+#define DEFAULT_LOGFILE_DIR "%windir%"
+#define DEFAULT_LOGFILE_NAME_PREFIX "vmware"
+#else
+// *ix log goes to /var/log/vmware-<service>.log
+#define DEFAULT_LOGFILE_NAME_PREFIX "/var/log/vmware"
+#endif
/** The "failsafe" handler. */
#if defined(_WIN32)
@@ -83,6 +105,7 @@
} \
g_free((handler)->domain); \
g_free((handler)->type); \
+ g_free((handler)->confData); \
g_free(handler); \
} \
} while (0)
@@ -103,24 +126,93 @@ typedef struct LogHandler {
guint mask;
guint handlerId;
gboolean inherited;
+ /**
+ * The log handlers that write to files need special
+ * treatment when guest has been quiesced.
+ */
+ gboolean needsFileIO;
+ gboolean isSysLog;
+ gchar *confData;
} LogHandler;
+/**
+ * Structure for caching a log message
+ */
+typedef struct LogEntry {
+ gchar *domain;
+ gchar *msg;
+ LogHandler *handler;
+ GLogLevelFlags level;
+} LogEntry;
+
+
static gchar *gLogDomain = NULL;
+static GPtrArray *gCachedLogs = NULL;
+static guint gDroppedLogCount = 0;
+static gint gMaxCacheEntries = DEFAULT_MAX_CACHE_ENTRIES;
static gboolean gEnableCoreDump = TRUE;
static gboolean gLogEnabled = FALSE;
static gboolean gGuestSDKMode = FALSE;
static guint gPanicCount = 0;
static LogHandler *gDefaultData;
static LogHandler *gErrorData;
+static LogHandler *gErrorSyslog;
static GPtrArray *gDomains = NULL;
static gboolean gLogInitialized = FALSE;
+static GStaticRecMutex gLogStateMutex = G_STATIC_REC_MUTEX_INIT;
static gboolean gLoggingStopped = FALSE;
+static gboolean gLogIOSuspended = FALSE;
/* Internal functions. */
/**
+ * Aborts the program, optionally creating a core dump.
+ */
+
+static INLINE NORETURN void
+VMToolsLogPanic(void)
+{
+ gPanicCount++;
+
+ /*
+ * Probably, flush the cached logs here. It is not
+ * critial though because we will have the cached
+ * logs in memory anyway.
+ */
+
+ if (gEnableCoreDump) {
+ /*
+ * TODO: Make sure to thaw the filesystem before dumping core.
+ */
+#if defined(_WIN32)
+ CoreDump_CoreDump();
+#else
+ char cwd[PATH_MAX];
+ if (getcwd(cwd, sizeof cwd) != NULL) {
+ if (access(cwd, W_OK) == -1) {
+ /*
+ * Can't write to the working dir. chdir() to the user's home
+ * directory as an attempt to get a valid core dump.
+ */
+ const char *home = getenv("HOME");
+ if (home != NULL) {
+ if (chdir(home)) {
+ /* Just to make glibc headers happy. */
+ }
+ }
+ }
+ }
+ abort();
+#endif
+ }
+ /* Same behavior as Panic_Panic(). */
+ exit(-1);
+}
+
+
+/**
* glib-based version of Str_Asprintf().
*
* @param[out] string Where to store the result.
@@ -153,6 +245,7 @@ VMToolsAsprintf(gchar **string,
* @param[in] domain Log domain.
* @param[in] level Log level.
* @param[in] data Log handler data.
+ * @param[in] cached If the message will be cached.
*
* @return Formatted log message according to the log domain's config.
* Should be g_free()'d.
@@ -162,13 +255,15 @@ static gchar *
VMToolsLogFormat(const gchar *message,
const gchar *domain,
GLogLevelFlags level,
- LogHandler *data)
+ LogHandler *data,
+ gboolean cached)
{
char *msg = NULL;
const char *slevel;
size_t len = 0;
gboolean shared = TRUE;
gboolean addsTimestamp = TRUE;
+ char *tstamp;
if (domain == NULL) {
domain = gLogDomain;
@@ -216,10 +311,9 @@ VMToolsLogFormat(const gchar *message,
addsTimestamp = data->logger->addsTimestamp;
}
- if (!addsTimestamp) {
- char *tstamp;
+ tstamp = System_GetTimeAsString();
- tstamp = System_GetTimeAsString();
+ if (!addsTimestamp) {
if (shared) {
len = VMToolsAsprintf(&msg, "[%s] [%8s] [%s:%s] %s\n",
(tstamp != NULL) ? tstamp : "no time",
@@ -229,16 +323,29 @@ VMToolsLogFormat(const gchar *message,
(tstamp != NULL) ? tstamp : "no time",
slevel, domain, message);
}
- free(tstamp);
} else {
- if (shared) {
- len = VMToolsAsprintf(&msg, "[%8s] [%s:%s] %s\n",
- slevel, gLogDomain, domain, message);
+ if (cached) {
+ if (shared) {
+ len = VMToolsAsprintf(&msg, "[cached at %s] [%8s] [%s:%s] %s\n",
+ (tstamp != NULL) ? tstamp : "no time",
+ slevel, gLogDomain, domain, message);
+ } else {
+ len = VMToolsAsprintf(&msg, "[cached at %s] [%8s] [%s] %s\n",
+ (tstamp != NULL) ? tstamp : "no time",
+ slevel, domain, message);
+ }
} else {
- len = VMToolsAsprintf(&msg, "[%8s] [%s] %s\n", slevel, domain, message);
+ if (shared) {
+ len = VMToolsAsprintf(&msg, "[%8s] [%s:%s] %s\n",
+ slevel, gLogDomain, domain, message);
+ } else {
+ len = VMToolsAsprintf(&msg, "[%8s] [%s] %s\n", slevel, domain, message);
+ }
}
}
+ free(tstamp);
+
/*
* The log messages from glib itself (and probably other libraries based
* on glib) do not include a trailing new line. Most of our code does. So
@@ -249,42 +356,68 @@ VMToolsLogFormat(const gchar *message,
msg[len - 1] = '\0';
}
+ if (!msg) {
+ /*
+ * Memory allocation failure?
+ */
+ VMToolsLogPanic();
+ }
+
return msg;
}
/**
- * Aborts the program, optionally creating a core dump.
+ * Function to free a cached LogEntry.
+ *
+ * @param[in] data Log entry to be freed.
*/
-static INLINE NORETURN void
-VMToolsLogPanic(void)
+static void
+VMToolsFreeLogEntry(gpointer data)
{
- gPanicCount++;
- if (gEnableCoreDump) {
-#if defined(_WIN32)
- CoreDump_CoreDump();
-#else
- char cwd[PATH_MAX];
- if (getcwd(cwd, sizeof cwd) != NULL) {
- if (access(cwd, W_OK) == -1) {
- /*
- * Can't write to the working dir. chdir() to the user's home
- * directory as an attempt to get a valid core dump.
- */
- const char *home = getenv("HOME");
- if (home != NULL) {
- if (chdir(home)) {
- /* Just to make glibc headers happy. */
- }
- }
- }
- }
- abort();
-#endif
+ LogEntry *entry = data;
+
+ g_free(entry->domain);
+ g_free(entry->msg);
+ g_free(entry);
+}
+
+
+/**
+ * Function that calls the log handler.
+ *
+ * Also, frees the _data to avoid having separate free call.
+ *
+ * @param[in] _data LogEntry pointer.
+ * @param[in] userData User data pointer.
+ */
+
+static void
+VMToolsLogMsg(gpointer _data, gpointer userData)
+{
+ LogEntry *entry = _data;
+ GlibLogger *logger = entry->handler->logger;
+ gboolean usedSyslog = FALSE;
+
+ if (logger != NULL) {
+ logger->logfn(entry->domain, entry->level, entry->msg, logger);
+ usedSyslog = entry->handler->isSysLog;
+ } else if (gErrorData->logger != NULL) {
+ gErrorData->logger->logfn(entry->domain, entry->level, entry->msg,
+ gErrorData->logger);
+ usedSyslog = gErrorData->isSysLog;
}
- /* Same behavior as Panic_Panic(). */
- exit(-1);
+
+ /*
+ * Any fatal errors need to go to syslog no matter what.
+ */
+ if (!usedSyslog && IS_FATAL(entry->level)) {
+ gErrorSyslog->logger->logfn(entry->domain, entry->level, entry->msg,
+ gErrorSyslog->logger);
+ }
+
+ VMToolsFreeLogEntry(entry);
}
@@ -307,18 +440,79 @@ VMToolsLog(const gchar *domain,
LogHandler *data = _data;
if (SHOULD_LOG(level, data)) {
- gchar *msg;
+ LogEntry *entry;
data = data->inherited ? gDefaultData : data;
- msg = VMToolsLogFormat(message, domain, level, data);
- if (data->logger != NULL) {
- data->logger->logfn(domain, level, msg, data->logger);
- } else if (gErrorData->logger != NULL) {
- gErrorData->logger->logfn(domain, level, msg, gErrorData->logger);
+ entry = g_malloc0(sizeof(LogEntry));
+ if (entry) {
+ entry->domain = domain ? g_strdup(domain) : NULL;
+ if (domain && !entry->domain) {
+ VMToolsLogPanic();
+ }
+ entry->handler = data;
+ entry->level = level;
+ }
+
+ if (gLogIOSuspended && data->needsFileIO) {
+ if (gMaxCacheEntries == 0) {
+ /* No way to log at this point, drop it */
+ VMToolsFreeLogEntry(entry);
+ gDroppedLogCount++;
+ goto exit;
+ }
+
+ entry->msg = VMToolsLogFormat(message, domain, level, data, TRUE);
+
+ /*
+ * Cache the log message
+ */
+ if (!gCachedLogs) {
+
+ /*
+ * If gMaxCacheEntries > 1K, start with 1/4th size
+ * to avoid frequent allocations
+ */
+ gCachedLogs = g_ptr_array_sized_new(gMaxCacheEntries < 1024 ?
+ gMaxCacheEntries :
+ gMaxCacheEntries/4);
+ if (!gCachedLogs) {
+ VMToolsLogPanic();
+ }
+
+ /*
+ * Some builds use glib version 2.16.4 which does not
+ * support g_ptr_array_set_free_func function
+ */
+ }
+
+ /*
+ * We don't expect logging to be suspended for a long time,
+ * so we can avoid putting a cap on cache size. However, we
+ * still have a default cap of 4K messages, just to be safe.
+ */
+ if (gCachedLogs->len < gMaxCacheEntries) {
+ g_ptr_array_add(gCachedLogs, entry);
+ } else {
+ /*
+ * Cache is full, drop the oldest log message. This is not
+ * very efficient but we don't expect this to be a common
+ * case anyway.
+ */
+ LogEntry *oldest = g_ptr_array_remove_index(gCachedLogs, 0);
+ VMToolsFreeLogEntry(oldest);
+ gDroppedLogCount++;
+
+ g_ptr_array_add(gCachedLogs, entry);
+ }
+
+ } else {
+ entry->msg = VMToolsLogFormat(message, domain, level, data, FALSE);
+ VMToolsLogMsg(entry, NULL);
}
- g_free(msg);
}
+
+exit:
if (IS_FATAL(level)) {
VMToolsLogPanic();
}
@@ -351,7 +545,18 @@ VMToolsGetLogFilePath(const gchar *key,
path = g_key_file_get_string(cfg, LOGGING_GROUP, key, NULL);
if (path == NULL) {
- return NULL;
+#ifdef WIN32
+ gchar winDir[MAX_PATH];
+
+ Win32U_ExpandEnvironmentStrings(DEFAULT_LOGFILE_DIR,
+ (LPSTR) winDir, sizeof winDir);
+ path = g_strdup_printf("%s%sTemp%s%s-%s.log",
+ winDir, DIRSEPS, DIRSEPS,
+ DEFAULT_LOGFILE_NAME_PREFIX, domain);
+#else
+ path = g_strdup_printf("%s-%s.log", DEFAULT_LOGFILE_NAME_PREFIX, domain);
+#endif
+ return path;
}
len = strlen(path);
@@ -387,7 +592,7 @@ VMToolsGetLogFilePath(const gchar *key,
if (len == 0) {
g_warning("Invalid path for domain '%s'.", domain);
- g_free(origPath);
+ g_free(path);
path = NULL;
}
}
@@ -421,13 +626,15 @@ VMToolsGetLogHandler(const gchar *handler,
{
LogHandler *logger;
GlibLogger *glogger = NULL;
+ gboolean needsFileIO = FALSE;
gchar key[MAX_DOMAIN_LEN + 64];
+ gboolean isSysLog = FALSE;
+ gchar *path = NULL;
if (strcmp(handler, "file") == 0 || strcmp(handler, "file+") == 0) {
gboolean append = strcmp(handler, "file+") == 0;
guint maxSize;
guint maxFiles;
- gchar *path;
GError *err = NULL;
/* Use the same type name for both. */
@@ -451,19 +658,24 @@ VMToolsGetLogHandler(const gchar *handler,
}
glogger = GlibUtils_CreateFileLogger(path, append, maxSize, maxFiles);
- g_free(path);
+ needsFileIO = TRUE;
} else {
g_warning("Missing path for domain '%s'.", domain);
}
} else if (strcmp(handler, "std") == 0) {
glogger = GlibUtils_CreateStdLogger();
+ needsFileIO = FALSE;
} else if (strcmp(handler, "vmx") == 0) {
glogger = VMToolsCreateVMXLogger();
+ needsFileIO = FALSE;
#if defined(_WIN32)
} else if (strcmp(handler, "outputdebugstring") == 0) {
glogger = GlibUtils_CreateDebugLogger();
+ needsFileIO = FALSE;
} else if (strcmp(handler, "syslog") == 0) {
glogger = GlibUtils_CreateEventLogger(L"VMware Tools", VMTOOLS_EVENT_LOG_MESSAGE);
+ needsFileIO = FALSE;
+ isSysLog = TRUE;
#else /* !_WIN32 */
} else if (strcmp(handler, "syslog") == 0) {
gchar *facility;
@@ -472,7 +684,12 @@ VMToolsGetLogHandler(const gchar *handler,
g_snprintf(key, sizeof key, "%s.facility", gLogDomain);
facility = g_key_file_get_string(cfg, LOGGING_GROUP, key, NULL);
glogger = GlibUtils_CreateSysLogger(domain, facility);
+ /*
+ * Older versions of Linux make synchronous call to syslog.
+ */
+ needsFileIO = TRUE;
g_free(facility);
+ isSysLog = TRUE;
#endif
} else {
g_warning("Invalid handler for domain '%s': %s", domain, handler);
@@ -487,6 +704,10 @@ VMToolsGetLogHandler(const gchar *handler,
logger->logger = glogger;
logger->mask = mask;
logger->type = strdup(handler);
+ logger->needsFileIO = needsFileIO;
+ logger->isSysLog = isSysLog;
+ logger->confData = (path != NULL ? g_strdup(path) : NULL);
+ g_free(path);
return logger;
}
@@ -517,6 +738,7 @@ VMToolsConfigLogDomain(const gchar *domain,
{
gchar *handler = NULL;
gchar *level = NULL;
+ gchar *confData = NULL;
gchar key[128];
gboolean isDefault = strcmp(domain, gLogDomain) == 0;
@@ -535,17 +757,16 @@ VMToolsConfigLogDomain(const gchar *domain,
g_snprintf(key, sizeof key, "%s.level", domain);
level = g_key_file_get_string(cfg, LOGGING_GROUP, key, NULL);
if (level == NULL) {
-#ifdef VMX86_DEBUG
- level = g_strdup("message");
-#else
- level = g_strdup("warning");
-#endif
+ level = g_strdup(VMTOOLS_LOGGING_LEVEL_DEFAULT);
}
/* Parse the handler information. */
g_snprintf(key, sizeof key, "%s.handler", domain);
handler = g_key_file_get_string(cfg, LOGGING_GROUP, key, NULL);
+ g_snprintf(key, sizeof key, "%s.data", domain);
+ confData = g_key_file_get_string(cfg, LOGGING_GROUP, key, NULL);
+
if (handler == NULL && isDefault) {
/*
* If no handler defined and we're configuring the default domain,
@@ -592,13 +813,17 @@ VMToolsConfigLogDomain(const gchar *domain,
* types as the same.
*/
const char *oldtype = oldDefault != NULL ? oldDefault->type : NULL;
+ const char *oldData = oldDefault != NULL ? oldDefault->confData : NULL;
if (oldtype != NULL && strcmp(oldtype, "file+") == 0) {
oldtype = "file";
}
if (isDefault && oldtype != NULL && strcmp(oldtype, handler) == 0) {
- data = oldDefault;
+ // check for a filename change
+ if (oldData && strcmp(oldData, confData) == 0) {
+ data = oldDefault;
+ }
} else if (oldDomains != NULL) {
guint i;
for (i = 0; i < oldDomains->len; i++) {
@@ -625,6 +850,8 @@ VMToolsConfigLogDomain(const gchar *domain,
data->domain = g_strdup(domain);
data->inherited = TRUE;
data->mask = levelsMask;
+ data->isSysLog = FALSE;
+ data->confData = g_strdup(confData);
}
if (isDefault) {
@@ -667,7 +894,9 @@ VMToolsResetLogging(gboolean hard)
g_log_set_default_handler(g_log_default_handler, NULL);
CLEAR_LOG_HANDLER(gErrorData);
+ CLEAR_LOG_HANDLER(gErrorSyslog);
gErrorData = NULL;
+ gErrorSyslog = NULL;
if (gDomains != NULL) {
guint i;
@@ -752,6 +981,7 @@ VMTools_ConfigLogging(const gchar *defaultDomain,
gchar **curr;
GPtrArray *oldDomains = NULL;
LogHandler *oldDefault = NULL;
+ GError *err = NULL;
g_return_if_fail(defaultDomain != NULL);
@@ -779,6 +1009,15 @@ VMTools_ConfigLogging(const gchar *defaultDomain,
cfg);
/*
+ * The syslog handler used for G_LOG_FLAG_FATAL.
+ * This is only used if the default handler isn't type 'syslog'.
+ */
+ gErrorSyslog = VMToolsGetLogHandler("syslog",
+ gLogDomain,
+ G_LOG_FLAG_FATAL,
+ cfg);
+
+ /*
* Configure the default domain first. See function documentation for
* VMToolsConfigLogDomain() for the reason.
*/
@@ -808,6 +1047,41 @@ VMTools_ConfigLogging(const gchar *defaultDomain,
g_strfreev(list);
gLogEnabled = g_key_file_get_boolean(cfg, LOGGING_GROUP, "log", NULL);
+
+ /*
+ * Need to set these so that the code below in this function
+ * can also log messages.
+ */
+ gLogEnabled |= force;
+ if (!gLogInitialized) {
+ gLogInitialized = TRUE;
+ g_static_rec_mutex_init(&gLogStateMutex);
+ }
+
+ gMaxCacheEntries = g_key_file_get_integer(cfg, LOGGING_GROUP,
+ "maxCacheEntries", &err);
+ if (err != NULL || gMaxCacheEntries < 0) {
+ /*
+ * Use default value in case of error.
+ * A value '0' will turn off log caching.
+ */
+ gMaxCacheEntries = DEFAULT_MAX_CACHE_ENTRIES;
+ if (err != NULL) {
+ if (err->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
+ g_warning("Invalid value for maxCacheEntries key: Error %d.",
+ err->code);
+ }
+ g_clear_error(&err);
+ }
+ }
+
+ if (gMaxCacheEntries > 0) {
+ g_message("Log caching is enabled with maxCacheEntries=%d.",
+ gMaxCacheEntries);
+ } else {
+ g_message("Log caching is disabled.");
+ }
+
if (g_key_file_has_key(cfg, LOGGING_GROUP, "enableCoreDump", NULL)) {
gEnableCoreDump = g_key_file_get_boolean(cfg, LOGGING_GROUP,
"enableCoreDump", NULL);
@@ -839,7 +1113,6 @@ VMTools_ConfigLogging(const gchar *defaultDomain,
* it's set to 5MB.
*/
if (gEnableCoreDump) {
- GError *err = NULL;
#if defined(_WIN32)
if (g_key_file_has_key(cfg, LOGGING_GROUP, "coreDumpFlags", NULL)) {
guint coreDumpFlags;
@@ -884,9 +1157,6 @@ VMTools_ConfigLogging(const gchar *defaultDomain,
#endif
}
- gLogEnabled |= force;
- gLogInitialized = TRUE;
-
if (allocDict) {
g_key_file_free(cfg);
}
@@ -920,10 +1190,13 @@ VMToolsLogWrapper(GLogLevelFlags level,
return;
}
+ VMTools_AcquireLogStateLock();
if (gLoggingStopped) {
/* This is to avoid nested logging in vmxLogger */
+ VMTools_ReleaseLogStateLock();
return;
}
+ VMTools_ReleaseLogStateLock();
if (gPanicCount == 0) {
char *msg = Str_Vasprintf(NULL, fmt, args);
@@ -941,7 +1214,30 @@ VMToolsLogWrapper(GLogLevelFlags level,
/**
+ * Acquire the log state lock.
+ */
+
+void
+VMTools_AcquireLogStateLock(void)
+{
+ g_static_rec_mutex_lock(&gLogStateMutex);
+}
+
+
+/**
+ * Release the log state lock.
+ */
+
+void
+VMTools_ReleaseLogStateLock(void)
+{
+ g_static_rec_mutex_unlock(&gLogStateMutex);
+}
+
+
+/**
* This is called to avoid nested logging in vmxLogger.
+ * NOTE: This must be called after acquiring LogState lock.
*/
void
@@ -953,6 +1249,7 @@ VMTools_StopLogging(void)
/**
* This is called to reset logging in vmxLogger.
+ * NOTE: This must be called after acquiring LogState lock.
*/
void
@@ -963,6 +1260,52 @@ VMTools_RestartLogging(void)
/**
+ * Suspend IO caused by logging activity.
+ */
+
+void
+VMTools_SuspendLogIO()
+{
+ gLogIOSuspended = TRUE;
+}
+
+
+/**
+ * Resume IO caused by logging activity.
+ */
+
+void
+VMTools_ResumeLogIO()
+{
+ guint cachedEntries = 0;
+
+ /*
+ * Resume the log IO first, so that we can also log messages
+ * from within this function itself!
+ */
+ gLogIOSuspended = FALSE;
+
+ /*
+ * Flush the cached log messages, if any
+ */
+ if (gCachedLogs) {
+ cachedEntries = gCachedLogs->len;
+ g_ptr_array_foreach(gCachedLogs, VMToolsLogMsg, NULL);
+ g_ptr_array_free(gCachedLogs, TRUE);
+ gCachedLogs = NULL;
+ }
+
+ g_debug("Flushed %u log messages from cache after resuming log IO.",
+ cachedEntries);
+
+ if (gDroppedLogCount > 0) {
+ g_warning("Dropped %u log messages from cache.", gDroppedLogCount);
+ gDroppedLogCount = 0;
+ }
+}
+
+
+/**
* Called if vmtools lib is used along with Guestlib SDK.
*/
@@ -1127,3 +1470,81 @@ Warning(const char *fmt, ...)
va_end(args);
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMTools_ChangeLogFilePath --
+ *
+ * This function gets the log file location given in the config file
+ * and appends the string provided just before the delimiter specified.
+ * If more than one delimiter is present in the string, it appends just
+ * before the first delimiter. If the delimiter does not exist in the
+ * location, the string provided is appended at the end of the location.
+ *
+ * NOTE: It is up to the caller to free the delimiter and append string.
+ *
+ * Example:
+ * 1) location - "C:\vmresset.log", delimiter - ".", appendString - "_4"
+ * location changed = "C:\vmresset_4.log"
+ * 2) location - "C:\vmresset", delimiter - ".", appendString - "_4"
+ * location changed = "C:\vmresset_4"
+ * 3) location - "C:\vmresset.log.log", delimiter - ".", appendString - "_4"
+ * location changed = "C:\vmresset_4.log.log"
+ *
+ * Results:
+ * TRUE if log file location is changed, FALSE otherwise.
+ *
+ * Side effects:
+ * Appends a string into the log file location.
+ *
+ *----------------------------------------------------------------------
+ */
+
+gboolean
+VMTools_ChangeLogFilePath(const gchar *delimiter, // IN
+ const gchar *appendString, // IN
+ const gchar *domain, // IN
+ GKeyFile *conf) // IN, OUT
+{
+ gchar key[128];
+ gchar *path = NULL;
+ gchar *userLogTemp = NULL;
+ gchar **tokens;
+ gboolean retVal = FALSE;
+
+ if (domain == NULL || conf == NULL){
+ goto exit;
+ }
+
+ g_snprintf(key, sizeof key, "%s.data", domain);
+ path = VMToolsGetLogFilePath(key, domain, conf);
+
+ if (path == NULL || appendString == NULL || delimiter == NULL){
+ goto exit;
+ }
+
+ tokens = g_strsplit(path, delimiter, 2);
+ if (tokens != NULL && *tokens != NULL){
+ userLogTemp = g_strjoin(appendString, *tokens, " ", NULL);
+ userLogTemp = g_strchomp (userLogTemp);
+ if (*(tokens+1) != NULL){
+ gchar *userLog;
+ userLog = g_strjoin(delimiter, userLogTemp, *(tokens+1), NULL);
+ g_key_file_set_string(conf, LOGGING_GROUP, key, userLog);
+ g_free(userLog);
+ } else {
+ g_key_file_set_string(conf, LOGGING_GROUP, key, userLogTemp);
+ }
+ retVal = TRUE;
+ g_free(userLogTemp);
+ }
+ g_strfreev(tokens);
+
+exit:
+ if (path){
+ g_free(path);
+ }
+
+ return retVal;
+}
diff --git a/open-vm-tools/libvmtools/vmxLogger.c b/open-vm-tools/libvmtools/vmxLogger.c
index 3eb5fa31..2e5ddf83 100644
--- a/open-vm-tools/libvmtools/vmxLogger.c
+++ b/open-vm-tools/libvmtools/vmxLogger.c
@@ -27,7 +27,6 @@
typedef struct VMXLoggerData {
GlibLogger handler;
- GStaticMutex lock;
RpcChannel *chan;
} VMXLoggerData;
@@ -60,8 +59,7 @@ VMXLoggerLog(const gchar *domain,
{
VMXLoggerData *logger = data;
- g_static_mutex_lock(&logger->lock);
-
+ VMTools_AcquireLogStateLock();
/*
* To avoid nested logging inside of RpcChannel, we need to disable logging
* here. See bug 1069390.
@@ -80,7 +78,7 @@ VMXLoggerLog(const gchar *domain,
}
VMTools_RestartLogging();
- g_static_mutex_unlock(&logger->lock);
+ VMTools_ReleaseLogStateLock();
}
@@ -100,7 +98,6 @@ VMXLoggerDestroy(gpointer data)
{
VMXLoggerData *logger = data;
RpcChannel_Destroy(logger->chan);
- g_static_mutex_free(&logger->lock);
g_free(logger);
}
@@ -124,7 +121,6 @@ VMToolsCreateVMXLogger(void)
data->handler.addsTimestamp = TRUE;
data->handler.shared = TRUE;
data->handler.dtor = VMXLoggerDestroy;
- g_static_mutex_init(&data->lock);
data->chan = RpcChannel_New();
return &data->handler;
}
diff --git a/open-vm-tools/modules/freebsd/vmblock/subr.c b/open-vm-tools/modules/freebsd/vmblock/subr.c
index 393110af..3c2acf84 100644
--- a/open-vm-tools/modules/freebsd/vmblock/subr.c
+++ b/open-vm-tools/modules/freebsd/vmblock/subr.c
@@ -1,5 +1,5 @@
/* **********************************************************
- * Copyright 2007 VMware, Inc. All rights reserved.
+ * Copyright 2007-2014 VMware, Inc. All rights reserved.
* **********************************************************/
/*
diff --git a/open-vm-tools/modules/freebsd/vmblock/vfsops.c b/open-vm-tools/modules/freebsd/vmblock/vfsops.c
index fb7a12f7..c9f080c9 100644
--- a/open-vm-tools/modules/freebsd/vmblock/vfsops.c
+++ b/open-vm-tools/modules/freebsd/vmblock/vfsops.c
@@ -1,5 +1,5 @@
/* **********************************************************
- * Copyright 2007 VMware, Inc. All rights reserved.
+ * Copyright 2007-2014 VMware, Inc. All rights reserved.
* **********************************************************/
/*
diff --git a/open-vm-tools/modules/freebsd/vmblock/vnops.c b/open-vm-tools/modules/freebsd/vmblock/vnops.c
index 4f0ad90c..84c95f05 100644
--- a/open-vm-tools/modules/freebsd/vmblock/vnops.c
+++ b/open-vm-tools/modules/freebsd/vmblock/vnops.c
@@ -1,5 +1,5 @@
/* **********************************************************
- * Copyright 2007 VMware, Inc. All rights reserved.
+ * Copyright 2007-2014 VMware, Inc. All rights reserved.
* **********************************************************/
/*
diff --git a/open-vm-tools/modules/freebsd/vmmemctl/os.c b/open-vm-tools/modules/freebsd/vmmemctl/os.c
index 1342edab..eed820c1 100644
--- a/open-vm-tools/modules/freebsd/vmmemctl/os.c
+++ b/open-vm-tools/modules/freebsd/vmmemctl/os.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2000 VMware, Inc. All rights reserved.
+ * Copyright (C) 2000,2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -544,10 +544,13 @@ os_balloonobject_create(void)
*/
PageHandle
-OS_ReservedPageAlloc(int canSleep) // IN
+OS_ReservedPageAlloc(int canSleep, // IN
+ int isLargePage) // IN
{
vm_page_t page;
+ ASSERT(!isLargePage);
+
page = os_kmem_alloc(canSleep);
if (page == NULL) {
return PAGE_HANDLE_INVALID;
@@ -574,8 +577,11 @@ OS_ReservedPageAlloc(int canSleep) // IN
*/
void
-OS_ReservedPageFree(PageHandle handle) // IN: A valid page handle
+OS_ReservedPageFree(PageHandle handle, // IN: A valid page handle
+ int isLargePage) // IN
{
+ ASSERT(!isLargePage);
+
os_kmem_free((vm_page_t)handle);
}
@@ -807,16 +813,16 @@ vmmemctl_sysctl(SYSCTL_HANDLER_ARGS)
stats->timer,
stats->start, stats->startFail,
stats->guestType, stats->guestTypeFail,
- stats->lock, stats->lockFail,
- stats->unlock, stats->unlockFail,
+ stats->lock[FALSE], stats->lockFail[FALSE],
+ stats->unlock[FALSE], stats->unlockFail[FALSE],
stats->target, stats->targetFail,
stats->primAlloc[BALLOON_PAGE_ALLOC_NOSLEEP],
stats->primAllocFail[BALLOON_PAGE_ALLOC_NOSLEEP],
stats->primAlloc[BALLOON_PAGE_ALLOC_CANSLEEP],
stats->primAllocFail[BALLOON_PAGE_ALLOC_CANSLEEP],
- stats->primFree,
- stats->primErrorPageAlloc,
- stats->primErrorPageFree);
+ stats->primFree[FALSE],
+ stats->primErrorPageAlloc[FALSE],
+ stats->primErrorPageFree[FALSE]);
return SYSCTL_OUT(req, buf, len + 1);
}
diff --git a/open-vm-tools/modules/linux/dkms.conf b/open-vm-tools/modules/linux/dkms.conf
index ffedc560..4c75c0f6 100644
--- a/open-vm-tools/modules/linux/dkms.conf
+++ b/open-vm-tools/modules/linux/dkms.conf
@@ -1,5 +1,5 @@
PACKAGE_NAME=open-vm-tools
-PACKAGE_VERSION=9.10.2
+PACKAGE_VERSION=10.0.0
MAKE_CMD_TMPL="make VM_UNAME=\$kernelver \
MODULEBUILDDIR=$dkms_tree/$PACKAGE_NAME/$PACKAGE_VERSION/build"
diff --git a/open-vm-tools/modules/linux/dkms.sh b/open-vm-tools/modules/linux/dkms.sh
index 650b5c94..ae9e748c 100644
--- a/open-vm-tools/modules/linux/dkms.sh
+++ b/open-vm-tools/modules/linux/dkms.sh
@@ -28,12 +28,12 @@ then
echo " src: root of unpacked open-vm-tools package"
echo " dst: where to create the dkms tree"
echo
- echo "The script will create an 'open-vm-tools' module with version 9.10.2."
+ echo "The script will create an 'open-vm-tools' module with version 10.0.0."
exit 1
fi
src=$1
-dst=$2/open-vm-tools-9.10.2
+dst=$2/open-vm-tools-10.0.0
SHARED_HEADERS="backdoor_def.h"
SHARED_HEADERS="$SHARED_HEADERS backdoor_types.h"
@@ -47,6 +47,7 @@ SHARED_HEADERS="$SHARED_HEADERS vm_atomic.h"
SHARED_HEADERS="$SHARED_HEADERS vm_basic_asm.h"
SHARED_HEADERS="$SHARED_HEADERS vm_basic_asm_x86.h"
SHARED_HEADERS="$SHARED_HEADERS vm_basic_asm_x86_64.h"
+SHARED_HEADERS="$SHARED_HEADERS vm_basic_asm_x86_common.h"
SHARED_HEADERS="$SHARED_HEADERS vm_basic_defs.h"
SHARED_HEADERS="$SHARED_HEADERS vm_basic_math.h"
SHARED_HEADERS="$SHARED_HEADERS vm_basic_types.h"
diff --git a/open-vm-tools/modules/linux/shared/autoconf/dalias.c b/open-vm-tools/modules/linux/shared/autoconf/dalias.c
new file mode 100644
index 00000000..2b8dc44c
--- /dev/null
+++ b/open-vm-tools/modules/linux/shared/autoconf/dalias.c
@@ -0,0 +1,48 @@
+/*********************************************************
+ * Copyright (C) 2015 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *********************************************************/
+
+#include "compat_version.h"
+#include "compat_autoconf.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+#include <linux/dcache.h>
+#include <linux/list.h>
+
+/*
+ * After 3.19.0, the dentry d_alias field was moved. Fedora
+ * backported this behavior into earlier kernel versions.
+ * The type of the d_alias field changed from 3.6 onwards
+ * which was a list head to being a list node. The check
+ * for earlier than 3.6 is done separately.
+ *
+ * This test will fail on a kernel with such a patch.
+ */
+void test(void)
+{
+ struct dentry aliasDentry;
+
+ INIT_HLIST_NODE(&aliasDentry.d_alias);
+}
+
+#else
+/* Intentionally passes for earlier than 3.6.0 kernels as a separate test is done. */
+#endif
+#else
+#error "This test intentionally fails on 3.19.0 or newer kernels."
+#endif
diff --git a/open-vm-tools/modules/linux/shared/autoconf/dalias1.c b/open-vm-tools/modules/linux/shared/autoconf/dalias1.c
new file mode 100644
index 00000000..457c20a2
--- /dev/null
+++ b/open-vm-tools/modules/linux/shared/autoconf/dalias1.c
@@ -0,0 +1,50 @@
+/*********************************************************
+ * Copyright (C) 2015 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *********************************************************/
+
+#include "compat_version.h"
+#include "compat_autoconf.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) && \
+ LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#include <linux/dcache.h>
+#include <linux/list.h>
+
+/*
+ * After 3.19.0, the dentry d_alias field was moved. Fedora
+ * backported this behavior into earlier kernels.
+ * The type of the d_alias field changed from 3.6 onwards
+ * which was a list head to being a list node. The check
+ * for 3.6 onwards is done separately.
+ *
+ * This test will fail on a kernel with such a patch.
+ */
+void test(void)
+{
+ struct dentry aliasDentry;
+
+ INIT_LIST_HEAD(&aliasDentry.d_alias);
+}
+
+#else
+/*
+ * Intentionally passes for earlier than 3.2.0 kernels as d_alias is valid.
+ *
+ * Intentionally passes for 3.6.0 or later kernels as d_alias is a different type.
+ * A separate test with the different type is run for those kernel versions.
+ */
+#endif
diff --git a/open-vm-tools/modules/linux/shared/autoconf/file_operations_flush.c b/open-vm-tools/modules/linux/shared/autoconf/file_operations_flush.c
index 818aee32..f1c77b23 100644
--- a/open-vm-tools/modules/linux/shared/autoconf/file_operations_flush.c
+++ b/open-vm-tools/modules/linux/shared/autoconf/file_operations_flush.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ * Copyright (C) 2013-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/shared/autoconf/truncate_pagecache.c b/open-vm-tools/modules/linux/shared/autoconf/truncate_pagecache.c
new file mode 100644
index 00000000..2ced8e0e
--- /dev/null
+++ b/open-vm-tools/modules/linux/shared/autoconf/truncate_pagecache.c
@@ -0,0 +1,52 @@
+/*********************************************************
+ * Copyright (C) 2015 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *********************************************************/
+
+#include "compat_version.h"
+#include "compat_autoconf.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && \
+ LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/types.h> /* loff_t */
+
+/*
+ * After 3.12.0, truncate_pagecache changed its interface to just use
+ * the new file size only. Red Hat backported this behavior into a 3.10.0
+ * kernel.
+ *
+ * This test will fail on a kernel with such a patch.
+ */
+
+void test(void)
+{
+ struct inode inode;
+ loff_t oldSize = 0;
+ loff_t newSize = 4096;
+
+ truncate_pagecache(&inode, oldSize, newSize);
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+#error "This test intentionally fails on 3.12.0 and newer kernels."
+#else
+/*
+ * It must be older than 2.6.32 in which case we assume success.
+ * So not 3.12 compatible. There is no function for these versions.
+ */
+#endif
diff --git a/open-vm-tools/modules/linux/shared/driverLog.c b/open-vm-tools/modules/linux/shared/driverLog.c
index 92d8f788..39779f34 100644
--- a/open-vm-tools/modules/linux/shared/driverLog.c
+++ b/open-vm-tools/modules/linux/shared/driverLog.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/shared/driverLog.h b/open-vm-tools/modules/linux/shared/driverLog.h
index 901ab98e..04dd07cd 100644
--- a/open-vm-tools/modules/linux/shared/driverLog.h
+++ b/open-vm-tools/modules/linux/shared/driverLog.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/shared/kernelStubsLinux.c b/open-vm-tools/modules/linux/shared/kernelStubsLinux.c
index b8579fca..e19faf7c 100644
--- a/open-vm-tools/modules/linux/shared/kernelStubsLinux.c
+++ b/open-vm-tools/modules/linux/shared/kernelStubsLinux.c
@@ -289,7 +289,7 @@ strdup(const char *source) // IN
/*
*----------------------------------------------------------------------------
*
- * malloc --
+ * mallocReal --
*
* Allocate memory using kmalloc. There is no realloc
* equivalent, so we roll our own by padding each allocation with
@@ -305,8 +305,8 @@ strdup(const char *source) // IN
*----------------------------------------------------------------------------
*/
-void *
-malloc(size_t size) // IN
+static void *
+mallocReal(size_t size) // IN
{
size_t *ptr;
ptr = kmalloc(size + sizeof size, GFP_KERNEL);
@@ -317,6 +317,34 @@ malloc(size_t size) // IN
return ptr;
}
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * malloc --
+ *
+ * Allocate memory using the common mallocReal.
+ *
+ * Note: This calls mallocReal and not malloc as the gcc 5.1.1 optimizer
+ * will replace the malloc and memset with a calloc call. This results
+ * in calloc calling itself and results in system crashes. See bug 1413226.
+ *
+ * Results:
+ * Pointer to driver heap memory, offset by 4 (or 8)
+ * bytes from the real block pointer.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void *
+malloc(size_t size) // IN
+{
+ return mallocReal(size);
+}
+
/*
*---------------------------------------------------------------------------
*
@@ -350,6 +378,10 @@ free(void *mem) // IN
*
* Malloc and zero.
*
+ * Note: This calls mallocReal and not malloc as the gcc 5.1.1 optimizer
+ * will replace the malloc and memset with a calloc call. This results
+ * for system crashes when used by kernel components. See bug 1413226.
+ *
* Results:
* Pointer to driver heap memory (see malloc, above).
*
@@ -367,7 +399,7 @@ calloc(size_t num, // IN
void *ptr;
size = num * len;
- ptr = malloc(size);
+ ptr = mallocReal(size);
if (ptr) {
memset(ptr, 0, size);
}
diff --git a/open-vm-tools/modules/linux/shared/kernelStubsSal.h b/open-vm-tools/modules/linux/shared/kernelStubsSal.h
index 6938aed5..36c9d0de 100644
--- a/open-vm-tools/modules/linux/shared/kernelStubsSal.h
+++ b/open-vm-tools/modules/linux/shared/kernelStubsSal.h
@@ -60,7 +60,7 @@
#define _When_(expr, annos)
#define _Printf_format_string_
#define _Use_decl_annotations_
-#elif _SAL_VERSION == 10
+#elif defined(_SAL_VERSION) && _SAL_VERSION == 10
// Microsoft didn't create a header mapping SAL 2.0 to 1.0. We do that here.
#define _In_ __in
#define _In_z_ __in_z
@@ -108,7 +108,7 @@
#define _Ret_allocates_malloc_mem_opt_z_bytecount_(_Size)
#define _Ret_allocates_malloc_mem_opt_z_
#define _In_frees_malloc_mem_opt_
-#elif _SAL_VERSION == 10
+#elif defined(_SAL_VERSION) && _SAL_VERSION == 10
#define _When_windrv_(annos) annos
#define _Ret_allocates_malloc_mem_opt_bytecap_(_Cap) __drv_allocatesMem("Memory") __checkReturn __post __byte_writableTo(_Cap) __exceptthat __maybenull
#define _Ret_allocates_malloc_mem_opt_bytecount_(_Count) __drv_allocatesMem("Memory") __checkReturn __post __byte_readableTo(_Count) __exceptthat __maybenull
diff --git a/open-vm-tools/modules/linux/shared/vmci_call_defs.h b/open-vm-tools/modules/linux/shared/vmci_call_defs.h
index 106800f0..ecfcbde7 100644
--- a/open-vm-tools/modules/linux/shared/vmci_call_defs.h
+++ b/open-vm-tools/modules/linux/shared/vmci_call_defs.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2006-2007 VMware, Inc. All rights reserved.
+ * Copyright (C) 2006-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/shared/vmci_defs.h b/open-vm-tools/modules/linux/shared/vmci_defs.h
index 74d314ff..da28b7f8 100644
--- a/open-vm-tools/modules/linux/shared/vmci_defs.h
+++ b/open-vm-tools/modules/linux/shared/vmci_defs.h
@@ -363,7 +363,11 @@ typedef uint32 VMCI_Event;
// this event has the Context payload type.
#define VMCI_EVENT_MEM_ACCESS_OFF 6 // Applicable to VMX and vmk. Same as
// above for the payload type.
-#define VMCI_EVENT_MAX 7
+#define VMCI_EVENT_GUEST_PAUSED 7 // Applicable to vmk. This event has the
+ // Context payload type.
+#define VMCI_EVENT_GUEST_UNPAUSED 8 // Applicable to vmk. Same as above for
+ // the payload type.
+#define VMCI_EVENT_MAX 9
/*
* Of the above events, a few are reserved for use in the VMX, and
@@ -383,7 +387,9 @@ typedef uint32 VMCI_Event;
#else // VMX86_SERVER
#define VMCI_EVENT_VALID(_event) (_event < VMCI_EVENT_MAX && \
_event != VMCI_EVENT_MEM_ACCESS_ON && \
- _event != VMCI_EVENT_MEM_ACCESS_OFF)
+ _event != VMCI_EVENT_MEM_ACCESS_OFF && \
+ _event != VMCI_EVENT_GUEST_PAUSED && \
+ _event != VMCI_EVENT_GUEST_UNPAUSED)
#endif // VMX86_SERVER
/* Reserved guest datagram resource ids. */
@@ -410,7 +416,7 @@ typedef uint32 VMCIPrivilegeFlags;
#define VMCI_PRIVILEGE_FLAG_RESTRICTED 0x01
#define VMCI_PRIVILEGE_FLAG_TRUSTED 0x02
#define VMCI_PRIVILEGE_ALL_FLAGS (VMCI_PRIVILEGE_FLAG_RESTRICTED | \
- VMCI_PRIVILEGE_FLAG_TRUSTED)
+ VMCI_PRIVILEGE_FLAG_TRUSTED)
#define VMCI_NO_PRIVILEGE_FLAGS 0x00
#define VMCI_DEFAULT_PROC_PRIVILEGE_FLAGS VMCI_NO_PRIVILEGE_FLAGS
#define VMCI_LEAST_PRIVILEGE_FLAGS VMCI_PRIVILEGE_FLAG_RESTRICTED
diff --git a/open-vm-tools/modules/linux/shared/vmci_iocontrols.h b/open-vm-tools/modules/linux/shared/vmci_iocontrols.h
index ce99894a..f00ea690 100644
--- a/open-vm-tools/modules/linux/shared/vmci_iocontrols.h
+++ b/open-vm-tools/modules/linux/shared/vmci_iocontrols.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007-2013 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -60,7 +60,7 @@
static INLINE void *
VMCIVA64ToPtr(VA64 va64) // IN
{
-#ifdef VM_X86_64
+#ifdef VM_64BIT
ASSERT_ON_COMPILE(sizeof (void *) == 8);
#else
ASSERT_ON_COMPILE(sizeof (void *) == 4);
diff --git a/open-vm-tools/modules/linux/shared/vmci_kernel_if.h b/open-vm-tools/modules/linux/shared/vmci_kernel_if.h
index ef8a5520..9def671a 100644
--- a/open-vm-tools/modules/linux/shared/vmci_kernel_if.h
+++ b/open-vm-tools/modules/linux/shared/vmci_kernel_if.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2006-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2006-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -88,7 +88,7 @@
#endif
#if defined(VMKERNEL)
- typedef SP_SpinLock VMCILock;
+ typedef MCSLock VMCILock;
typedef SP_IRQL VMCILockFlags;
typedef Semaphore VMCIEvent;
typedef Semaphore VMCIMutex;
@@ -145,8 +145,18 @@ typedef int (*VMCIEventReleaseCB)(void *clientData);
#define VMCI_SEMA_RANK_QPHEADER (SEMA_RANK_FS - 1)
- #define VMCI_LOCK_RANK_MAX (MIN(SP_RANK_WAIT, \
+ #define VMCI_LOCK_RANK_MAX_NONBLOCK (MIN(SP_RANK_WAIT, \
SP_RANK_HEAPLOCK_DYNAMIC) - 1)
+ #define VMCI_LOCK_RANK_MAX (SP_RANK_BLOCKABLE_HIGHEST_MAJOR - 2)
+
+ /*
+ * Determines whether VMCI locks will be blockable or not. If blockable,
+ * all locks will be at or below VMCI_LOCK_RANK_MAX. If not, locks will
+ * instead use VMCI_LOCK_RANK_MAX_NONBLOCK as the maximum. The other
+ * VMCI_LOCK_RANK_XXX values will be rebased to be non-blocking as well
+ * in that case.
+ */
+ extern Bool vmciBlockableLock;
#else
typedef unsigned long VMCILockRank;
typedef unsigned long VMCISemaRank;
diff --git a/open-vm-tools/modules/linux/vmci/common/vmciContext.c b/open-vm-tools/modules/linux/vmci/common/vmciContext.c
index 5ebd28ab..d2d03622 100644
--- a/open-vm-tools/modules/linux/vmci/common/vmciContext.c
+++ b/open-vm-tools/modules/linux/vmci/common/vmciContext.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2006-2012,2014 VMware, Inc. All rights reserved.
+ * Copyright (C) 2006-2012,2014-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -48,7 +48,8 @@ static int VMCIContextFireNotification(VMCIId contextID,
VMCIPrivilegeFlags privFlags);
#if defined(VMKERNEL)
static void VMCIContextReleaseGuestMemLocked(VMCIContext *context,
- VMCIGuestMemID gid);
+ VMCIGuestMemID gid,
+ Bool powerOff);
static void VMCIContextInFilterCleanup(VMCIContext *context);
#endif
@@ -1228,6 +1229,98 @@ VMCIContext_SetId(VMCIContext *context, // IN
context->cid = cid;
VMCI_ReleaseLock(&context->lock, flags);
}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContextGenerateEvent --
+ *
+ * Generates a VMCI event that only takes context ID as event data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+VMCIContextGenerateEvent(VMCIId cid, // IN
+ VMCI_Event event) // IN
+{
+ VMCIEventMsg *eMsg;
+ VMCIEventPayload_Context *ePayload;
+ /* buf is only 48 bytes. */
+ char buf[sizeof *eMsg + sizeof *ePayload];
+
+ eMsg = (VMCIEventMsg *)buf;
+ ePayload = VMCIEventMsgPayload(eMsg);
+
+ eMsg->hdr.dst = VMCI_MAKE_HANDLE(VMCI_HOST_CONTEXT_ID, VMCI_EVENT_HANDLER);
+ eMsg->hdr.src = VMCI_MAKE_HANDLE(VMCI_HYPERVISOR_CONTEXT_ID,
+ VMCI_CONTEXT_RESOURCE_ID);
+ eMsg->hdr.payloadSize = sizeof *eMsg + sizeof *ePayload - sizeof eMsg->hdr;
+ eMsg->eventData.event = event;
+ ePayload->contextID = cid;
+
+ (void)VMCIEvent_Dispatch((VMCIDatagram *)eMsg);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContext_NotifyGuestPaused --
+ *
+ * Notify subscribers of a execution state change of the VM
+ * with the given context ID. This will happen when a VM is
+ * quiesced/unquiesced.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+VMCIContext_NotifyGuestPaused(VMCIId cid, // IN
+ Bool paused) // IN
+{
+ VMCIContextGenerateEvent(cid, paused ? VMCI_EVENT_GUEST_PAUSED :
+ VMCI_EVENT_GUEST_UNPAUSED);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContext_NotifyMemoryAccess --
+ *
+ * Notify subscribers of a memory access change to the device.
+ * This can occur when the device is enabled/disabled/reset.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+VMCIContext_NotifyMemoryAccess(VMCIId cid, // IN
+ Bool on) // IN
+{
+ VMCIContextGenerateEvent(cid, on ? VMCI_EVENT_MEM_ACCESS_ON :
+ VMCI_EVENT_MEM_ACCESS_OFF);
+}
#endif
@@ -2589,7 +2682,8 @@ VMCIContext_RegisterGuestMem(VMCIContext *context, // IN: Context structure
* execution of the source VMX following a failed FSR.
*/
- VMCIContextReleaseGuestMemLocked(context, context->curGuestMemID);
+ VMCIContextReleaseGuestMemLocked(context, context->curGuestMemID,
+ FALSE);
} else {
/*
* When unquiescing the device during a restore sync not part
@@ -2653,15 +2747,20 @@ out:
static void
VMCIContextReleaseGuestMemLocked(VMCIContext *context, // IN: Context structure
- VMCIGuestMemID gid) // IN: Reference to guest
+ VMCIGuestMemID gid, // IN: Reference to guest
+ Bool powerOff) // IN: Device going away
{
uint32 numQueuePairs;
uint32 cur;
+ if (powerOff) {
+ VMCIContext_NotifyMemoryAccess(context->cid, FALSE);
+ }
+
/*
* It is safe to access the queue pair array here, since no changes
* to the queuePairArray can take place when the the quiescing
- * has been initiated.
+ * has been initiated, or when the device is being cleaned up.
*/
numQueuePairs = VMCIHandleArray_GetSize(context->queuePairArray);
@@ -2704,7 +2803,8 @@ VMCIContextReleaseGuestMemLocked(VMCIContext *context, // IN: Context structure
void
VMCIContext_ReleaseGuestMem(VMCIContext *context, // IN: Context structure
- VMCIGuestMemID gid) // IN: Reference to guest
+ VMCIGuestMemID gid, // IN: Reference to guest
+ Bool powerOff) // IN: Device is going away
{
#ifdef VMKERNEL
VMCIMutex_Acquire(&context->guestMemMutex);
@@ -2719,7 +2819,7 @@ VMCIContext_ReleaseGuestMem(VMCIContext *context, // IN: Context structure
* memory, if this is the same gid, that registered the memory.
*/
- VMCIContextReleaseGuestMemLocked(context, gid);
+ VMCIContextReleaseGuestMemLocked(context, gid, powerOff);
context->curGuestMemID = INVALID_VMCI_GUEST_MEM_ID;
}
diff --git a/open-vm-tools/modules/linux/vmci/common/vmciContext.h b/open-vm-tools/modules/linux/vmci/common/vmciContext.h
index 07fc3658..6ec9c30e 100644
--- a/open-vm-tools/modules/linux/vmci/common/vmciContext.h
+++ b/open-vm-tools/modules/linux/vmci/common/vmciContext.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2006-2013 VMware, Inc. All rights reserved.
+ * Copyright (C) 2006-2013,2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -65,6 +65,8 @@ Bool VMCIContext_RemoveHnd(VMCIContext *context,
uint32 *numNew);
void VMCIContext_ClearDatagrams(VMCIContext *context);
void VMCIContext_SetId(VMCIContext *context, VMCIId cid);
+void VMCIContext_NotifyGuestPaused(VMCIId cid, Bool paused);
+void VMCIContext_NotifyMemoryAccess(VMCIId cid, Bool on);
#endif
Bool VMCIContext_SupportsHostQP(VMCIContext *context);
void VMCIContext_ReleaseContext(VMCIContext *context);
@@ -84,7 +86,8 @@ int VMCIContext_GetCheckpointState(VMCIId contextID, uint32 cptType,
int VMCIContext_SetCheckpointState(VMCIId contextID, uint32 cptType,
uint32 numCIDs, char *cptBuf);
void VMCIContext_RegisterGuestMem(VMCIContext *context, VMCIGuestMemID gid);
-void VMCIContext_ReleaseGuestMem(VMCIContext *context, VMCIGuestMemID gid);
+void VMCIContext_ReleaseGuestMem(VMCIContext *context, VMCIGuestMemID gid,
+ Bool powerOff);
int VMCIContext_QueuePairCreate(VMCIContext *context, VMCIHandle handle);
int VMCIContext_QueuePairDestroy(VMCIContext *context, VMCIHandle handle);
diff --git a/open-vm-tools/modules/linux/vmci/common/vmciEvent.c b/open-vm-tools/modules/linux/vmci/common/vmciEvent.c
index 0d6a569c..ee781d0f 100644
--- a/open-vm-tools/modules/linux/vmci/common/vmciEvent.c
+++ b/open-vm-tools/modules/linux/vmci/common/vmciEvent.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -563,13 +563,15 @@ VMCIEventRegisterSubscription(VMCISubscription *sub, // IN
/*
* In the vmkernel we defer delivery of events to a helper world. This
* makes the event delivery more consistent across hosts and guests with
- * regard to which locks are held. Memory access events are an exception
- * to this, since clients need to know immediately that the device
- * memory is disabled (if we delay such events, then clients may be
- * notified too late).
+ * regard to which locks are held. Memory access and guest paused events
+ * are an exception to this, since clients need to know immediately that
+ * the device memory is disabled (if we delay such events, then clients
+ * may be notified too late).
*/
if (VMCI_EVENT_MEM_ACCESS_ON == event ||
- VMCI_EVENT_MEM_ACCESS_OFF == event) {
+ VMCI_EVENT_MEM_ACCESS_OFF == event ||
+ VMCI_EVENT_GUEST_PAUSED == event ||
+ VMCI_EVENT_GUEST_UNPAUSED == event) {
/*
* Client must expect to get such events synchronously, and should
* perform its locking accordingly. If it can't handle this, then
diff --git a/open-vm-tools/modules/linux/vmci/common/vmciQueuePair.c b/open-vm-tools/modules/linux/vmci/common/vmciQueuePair.c
index a4e511e3..e7a805fc 100644
--- a/open-vm-tools/modules/linux/vmci/common/vmciQueuePair.c
+++ b/open-vm-tools/modules/linux/vmci/common/vmciQueuePair.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/vmci/linux/driver.c b/open-vm-tools/modules/linux/vmci/linux/driver.c
index 58e23c2a..64a3cca6 100644
--- a/open-vm-tools/modules/linux/vmci/linux/driver.c
+++ b/open-vm-tools/modules/linux/vmci/linux/driver.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2011-2013 VMware, Inc. All rights reserved.
+ * Copyright (C) 2011-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/vmci/linux/vmci_version.h b/open-vm-tools/modules/linux/vmci/linux/vmci_version.h
index ee56876d..aecf0b6d 100644
--- a/open-vm-tools/modules/linux/vmci/linux/vmci_version.h
+++ b/open-vm-tools/modules/linux/vmci/linux/vmci_version.h
@@ -25,8 +25,8 @@
#ifndef _VMCI_VERSION_H_
#define _VMCI_VERSION_H_
-#define VMCI_DRIVER_VERSION 9.7.1.0
-#define VMCI_DRIVER_VERSION_COMMAS 9,7,1,0
-#define VMCI_DRIVER_VERSION_STRING "9.7.1.0"
+#define VMCI_DRIVER_VERSION 9.8.1.0
+#define VMCI_DRIVER_VERSION_COMMAS 9,8,1,0
+#define VMCI_DRIVER_VERSION_STRING "9.8.1.0"
#endif /* _VMCI_VERSION_H_ */
diff --git a/open-vm-tools/modules/linux/vmci/shared/pgtbl.h b/open-vm-tools/modules/linux/vmci/shared/pgtbl.h
index ed1ae8a1..39ef4e19 100644
--- a/open-vm-tools/modules/linux/vmci/shared/pgtbl.h
+++ b/open-vm-tools/modules/linux/vmci/shared/pgtbl.h
@@ -46,10 +46,10 @@
*-----------------------------------------------------------------------------
*/
-static INLINE MPN64
+static INLINE MPN
PgtblPte2MPN(pte_t *pte) // IN
{
- MPN64 mpn;
+ MPN mpn;
if (pte_present(*pte) == 0) {
return INVALID_MPN;
}
@@ -185,7 +185,7 @@ PgtblVa2PTELocked(struct mm_struct *mm, // IN: Mm structure of a process
*-----------------------------------------------------------------------------
*/
-static INLINE MPN64
+static INLINE MPN
PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process
VA addr) // IN: Address in the virtual address
{
@@ -193,7 +193,7 @@ PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process
pte = PgtblVa2PTELocked(mm, addr);
if (pte != NULL) {
- MPN64 mpn = PgtblPte2MPN(pte);
+ MPN mpn = PgtblPte2MPN(pte);
pte_unmap(pte);
return mpn;
}
@@ -222,7 +222,7 @@ PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process
*-----------------------------------------------------------------------------
*/
-static INLINE MPN64
+static INLINE MPN
PgtblKVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a caller
VA addr) // IN: Address in the virtual address
{
@@ -230,7 +230,7 @@ PgtblKVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a caller
pte = PgtblPGD2PTELocked(compat_pgd_offset_k(mm, addr), addr);
if (pte != NULL) {
- MPN64 mpn = PgtblPte2MPN(pte);
+ MPN mpn = PgtblPte2MPN(pte);
pte_unmap(pte);
return mpn;
}
@@ -290,11 +290,11 @@ PgtblVa2PageLocked(struct mm_struct *mm, // IN: Mm structure of a process
*-----------------------------------------------------------------------------
*/
-static INLINE MPN64
+static INLINE MPN
PgtblVa2MPN(VA addr) // IN
{
struct mm_struct *mm;
- MPN64 mpn;
+ MPN mpn;
/* current->mm is NULL for kernel threads, so use active_mm. */
mm = current->active_mm;
@@ -327,11 +327,11 @@ PgtblVa2MPN(VA addr) // IN
*-----------------------------------------------------------------------------
*/
-static INLINE MPN64
+static INLINE MPN
PgtblKVa2MPN(VA addr) // IN
{
struct mm_struct *mm = current->active_mm;
- MPN64 mpn;
+ MPN mpn;
if (compat_get_page_table_lock(mm)) {
spin_lock(compat_get_page_table_lock(mm));
diff --git a/open-vm-tools/modules/linux/vmhgfs/Makefile.kernel b/open-vm-tools/modules/linux/vmhgfs/Makefile.kernel
index c68a8087..fe6126a3 100644
--- a/open-vm-tools/modules/linux/vmhgfs/Makefile.kernel
+++ b/open-vm-tools/modules/linux/vmhgfs/Makefile.kernel
@@ -35,8 +35,9 @@ EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/getsb1.c,, -DVMW_GETSB_26
EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/statfs1.c,, -DVMW_STATFS_2618)
EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/inode1.c,, -DVMW_INODE_2618)
EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/dcount.c,, -DVMW_DCOUNT_311)
-
-MODPOST_VMCI_SYMVERS := $(wildcard $(MODULEBUILDDIR)/VMwareVMCIModule.symvers)
+EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/dalias.c,, -DVMW_DALIAS_319)
+EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/dalias1.c,, -DVMW_DALIAS_319)
+EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/truncate_pagecache.c,, -DVMW_PAGECACHE_312)
obj-m += $(DRIVER).o
@@ -117,19 +118,3 @@ clean:
rm -rf $(wildcard $(DRIVER).mod.c $(DRIVER).ko .tmp_versions \
Module.symvers Modules.symvers Module.markers modules.order \
$(foreach dir,./,$(addprefix $(dir),.*.cmd .*.o.flags *.o)))
-
-
-#
-# vmhgfs kernel module uses symbols from the VMCI kernel module. Copy the
-# Module.symvers file here so that the vmhgfs module knows about the VMCI version.
-# This is not done for tar builds because the tools install takes care of it.
-#
-prebuild::
-ifneq ($(MODULEBUILDDIR),)
-ifeq ($(MODPOST_VMCI_SYMVERS),)
- $(shell echo >&2 "Building vmhgfs without VMCI module symbols.")
-else
- $(shell echo >&2 "Building vmhgfs with VMCI module symbols.")
- cp -f $(MODPOST_VMCI_SYMVERS) $(SRCROOT)/Module.symvers
-endif
-endif
diff --git a/open-vm-tools/modules/linux/vmhgfs/dir.c b/open-vm-tools/modules/linux/vmhgfs/dir.c
index 809611a1..718be2e5 100644
--- a/open-vm-tools/modules/linux/vmhgfs/dir.c
+++ b/open-vm-tools/modules/linux/vmhgfs/dir.c
@@ -879,16 +879,22 @@ HgfsGetFileInode(HgfsAttrInfo const *attr, // IN: Attrs to use
struct super_block *sb) // IN: Superblock of this fs
{
ino_t inodeEntry;
+ uint64 tempIno;
+ HgfsSuperInfo *si;
ASSERT(attr);
ASSERT(sb);
- if (attr->mask & HGFS_ATTR_VALID_FILEID) {
- inodeEntry = attr->hostFileId;
+ si = HGFS_SB_TO_COMMON(sb);
+
+ if ((si->mntFlags & HGFS_MNT_SERVER_INUM) != 0 &&
+ (attr->mask & HGFS_ATTR_VALID_FILEID) != 0) {
+ tempIno = attr->hostFileId;
} else {
- inodeEntry = iunique(sb, HGFS_RESERVED_INO);
+ tempIno = iunique(sb, HGFS_RESERVED_INO);
}
+ inodeEntry = HgfsUniqueidToIno(tempIno);
LOG(4, (KERN_DEBUG "VMware hgfs: %s: return %lu\n", __func__, inodeEntry));
return inodeEntry;
}
diff --git a/open-vm-tools/modules/linux/vmhgfs/file.c b/open-vm-tools/modules/linux/vmhgfs/file.c
index bbde3f4b..0bc5ee34 100644
--- a/open-vm-tools/modules/linux/vmhgfs/file.c
+++ b/open-vm-tools/modules/linux/vmhgfs/file.c
@@ -877,6 +877,7 @@ HgfsFileWrite(struct kiocb *iocb, // IN: I/O control block
{
ssize_t result;
struct dentry *writeDentry;
+ HgfsInodeInfo *iinfo;
loff_t pos;
unsigned long iovSegs;
@@ -889,11 +890,27 @@ HgfsFileWrite(struct kiocb *iocb, // IN: I/O control block
iovSegs = HGFS_IOV_TO_SEGS(iov, numSegs);
writeDentry = iocb->ki_filp->f_dentry;
+ iinfo = INODE_GET_II_P(writeDentry->d_inode);
LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s)\n",
__func__, writeDentry->d_parent->d_name.name,
writeDentry->d_name.name));
+
+ spin_lock(&writeDentry->d_inode->i_lock);
+ /*
+ * Guard against dentry revalidation invalidating the inode underneath us.
+ *
+ * Data is being written and may have valid data in a page in the cache.
+ * This action prevents any invalidating of the inode when a flushing of
+ * cache data occurs prior to syncing the file with the server's attributes.
+ * The flushing of cache data would empty our in memory write pages list and
+ * would cause the inode modified write time to be updated and so the inode
+ * would also be invalidated.
+ */
+ iinfo->numWbPages++;
+ spin_unlock(&writeDentry->d_inode->i_lock);
+
result = HgfsRevalidate(writeDentry);
if (result) {
LOG(4, (KERN_DEBUG "VMware hgfs: %s: invalid dentry\n", __func__));
@@ -917,7 +934,10 @@ HgfsFileWrite(struct kiocb *iocb, // IN: I/O control block
}
}
- out:
+out:
+ spin_lock(&writeDentry->d_inode->i_lock);
+ iinfo->numWbPages--;
+ spin_unlock(&writeDentry->d_inode->i_lock);
return result;
}
diff --git a/open-vm-tools/modules/linux/vmhgfs/filesystem.c b/open-vm-tools/modules/linux/vmhgfs/filesystem.c
index 33c4c56f..10dd8ab9 100644
--- a/open-vm-tools/modules/linux/vmhgfs/filesystem.c
+++ b/open-vm-tools/modules/linux/vmhgfs/filesystem.c
@@ -221,12 +221,22 @@ HgfsInitSuperInfo(HgfsMountInfo *mountInfo) // IN: Passed down from the user
}
/*
+ * Initialize with the default flags.
+ */
+ si->mntFlags = 0;
+ if ((mountInfo->flags & HGFS_MNTINFO_SERVER_INO) != 0) {
+ si->mntFlags |= HGFS_MNT_SERVER_INUM;
+ }
+
+ /*
* If the mounter specified a uid or gid, we will prefer them over any uid
* or gid given to us by the server.
*/
- si->uidSet = mountInfo->uidSet;
+ if (mountInfo->uidSet) {
+ si->mntFlags |= HGFS_MNT_SET_UID;
+ }
si->uid = current_uid();
- if (si->uidSet) {
+ if ((si->mntFlags & HGFS_MNT_SET_UID) != 0) {
kuid_t mntUid = make_kuid(current_user_ns(), mountInfo->uid);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
if (uid_valid(mntUid))
@@ -234,9 +244,11 @@ HgfsInitSuperInfo(HgfsMountInfo *mountInfo) // IN: Passed down from the user
si->uid = mntUid;
}
- si->gidSet = mountInfo->gidSet;
+ if (mountInfo->gidSet) {
+ si->mntFlags |= HGFS_MNT_SET_GID;
+ }
si->gid = current_gid();
- if (si->gidSet) {
+ if ((si->mntFlags & HGFS_MNT_SET_GID) != 0) {
kgid_t mntGid = make_kgid(current_user_ns(), mountInfo->gid);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
if (gid_valid(mntGid))
@@ -372,9 +384,9 @@ HgfsReadSuper(struct super_block *sb, // OUT: Superblock object
mountInfo = (HgfsMountInfo *)rawData;
if (!mountInfo ||
mountInfo->magicNumber != HGFS_SUPER_MAGIC ||
+ mountInfo->infoSize != sizeof *mountInfo ||
mountInfo->version != HGFS_PROTOCOL_VERSION) {
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsReadSuper: bad mount data passed "
- "in by user, failing!\n"));
+ LOG(4, (KERN_CRIT LGPFX "%s: bad mount data passed\n", __func__));
return -EINVAL;
}
diff --git a/open-vm-tools/modules/linux/vmhgfs/fsutil.c b/open-vm-tools/modules/linux/vmhgfs/fsutil.c
index 50233242..8c21c949 100644
--- a/open-vm-tools/modules/linux/vmhgfs/fsutil.c
+++ b/open-vm-tools/modules/linux/vmhgfs/fsutil.c
@@ -30,9 +30,9 @@
/* Must come before compat_dcache. */
#include "compat_fs.h"
-
#include "compat_dcache.h"
#include "compat_kernel.h"
+#include "compat_mm.h"
#include "compat_sched.h"
#include "compat_slab.h"
#include "compat_spinlock.h"
@@ -47,19 +47,50 @@
#include "hgfsProto.h"
#include "vm_basic_types.h"
+/*
+ * The get inode descriptor object.
+ */
+typedef struct HgfsInodeAttrDesc {
+ uint32 flags;
+ const HgfsAttrInfo *attr;
+} HgfsInodeAttrDesc;
+
+#define HGFS_INO_DESC_INO_FAKE (1 << 0)
+#define HGFS_INO_DESC_INO_COLLISION (1 << 1)
+
static void HgfsSetFileType(struct inode *inode,
HgfsAttrInfo const *attr);
static int HgfsUnpackGetattrReply(HgfsReq *req,
HgfsAttrInfo *attr,
char **fileName);
-static int HgfsPackGetattrRequest(HgfsReq *req,
- HgfsOp opUsed,
- Bool allowHandleReuse,
- struct dentry *dentry,
- HgfsAttrInfo *attr);
static int HgfsBuildRootPath(char *buffer,
size_t bufferLen,
HgfsSuperInfo *si);
+static int HgfsBuildFullPath(char *buffer,
+ size_t bufferLen,
+ HgfsSuperInfo *si,
+ struct dentry *dentry);
+static struct inode *HgfsGetInode(struct super_block *sb,
+ ino_t ino,
+ HgfsInodeAttrDesc *iattrDesc);
+static void HgfsDoReadInode(struct inode *inode);
+static int HgfsInitInode(struct inode *inode,
+ void *opaque);
+static int HgfsFindInode(struct inode *inode,
+ void *opaque);
+
+/*
+ * For kernels that are older than 2.6.32 there is no truncate_pagecache call
+ * so we set an empty macro.
+ * If we have the call then we check for kernel 3.12 compatibility.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+#define HGFS_TRUNCATE_PAGE_CACHE(inode, oldSize, newSize)
+#elif defined VMW_PAGECACHE_312 || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+#define HGFS_TRUNCATE_PAGE_CACHE(inode, oldSize, newSize) truncate_pagecache(inode, newSize)
+#else
+#define HGFS_TRUNCATE_PAGE_CACHE(inode, oldSize, newSize) truncate_pagecache(inode, oldSize, newSize)
+#endif
/*
* Private function implementations.
@@ -93,6 +124,57 @@ set_nlink(struct inode *inode, unsigned int nlink)
/*
*----------------------------------------------------------------------
*
+ * HgfsGetFileType --
+ *
+ * Get file type from the inode mode.
+ *
+ * Results:
+ * The file type.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static HgfsFileType
+HgfsGetFileType(struct inode *inode) // IN: Attrs to use
+{
+ HgfsFileType type;
+
+ ASSERT(inode != NULL);
+
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFLNK:
+ type = HGFS_FILE_TYPE_SYMLINK;
+ break;
+
+ case S_IFREG:
+ type = HGFS_FILE_TYPE_REGULAR;
+ break;
+
+ case S_IFDIR:
+ type = HGFS_FILE_TYPE_DIRECTORY;
+ break;
+
+ default:
+ /*
+ * XXX Should never happen. Since there aren't any other HGFS supported type.
+ */
+ LOG(4, (KERN_DEBUG LGPFX "%s: UNSUPPORTED inode type %d\n",
+ __func__, inode->i_mode & S_IFMT));
+ type = 0;
+ break;
+ }
+
+ LOG(10, (KERN_DEBUG LGPFX "%s: return %d\n", __func__, type));
+ return type;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* HgfsSetFileType --
*
* Set file type in inode according to the hgfs attributes.
@@ -260,15 +342,13 @@ HgfsUnpackGetattrReply(HgfsReq *req, // IN: Reply packet
static int
HgfsPackCommonattr(HgfsReq *req, // IN/OUT: request buffer
HgfsOp opUsed, // IN: Op to be used
- Bool allowHandleReuse, // IN: Can we use a handle?
- struct inode *fileInode, // IN: file inode
+ HgfsHandle handle, // IN: file handle to use if valid
size_t *reqSize, // OUT: request size
size_t *reqBufferSize, // OUT: request buffer size
char **fileName, // OUT: pointer to request file name
uint32 **fileNameLength, // OUT: pointer to request file name length
HgfsAttrInfo *attr) // OUT: Attrs to update
{
- HgfsHandle handle;
int result = 0;
attr->requestType = opUsed;
@@ -292,9 +372,7 @@ HgfsPackCommonattr(HgfsReq *req, // IN/OUT: request buffer
* by name.
*/
requestV3->hints = 0;
- if (allowHandleReuse && HgfsGetHandle(fileInode,
- 0,
- &handle) == 0) {
+ if (handle != HGFS_INVALID_HANDLE) {
requestV3->fileName.flags = HGFS_FILE_NAME_USE_FILE_DESC;
requestV3->fileName.fid = handle;
requestV3->fileName.length = 0;
@@ -327,9 +405,7 @@ HgfsPackCommonattr(HgfsReq *req, // IN/OUT: request buffer
* correct regardless. If we don't find a handle, fall back on getattr
* by name.
*/
- if (allowHandleReuse && HgfsGetHandle(fileInode,
- 0,
- &handle) == 0) {
+ if (handle != HGFS_INVALID_HANDLE) {
requestV2->hints = HGFS_ATTR_HINT_USE_FILE_DESC;
requestV2->file = handle;
*fileName = NULL;
@@ -371,7 +447,7 @@ HgfsPackCommonattr(HgfsReq *req, // IN/OUT: request buffer
/*
*----------------------------------------------------------------------
*
- * HgfsPackGetattrRequest --
+ * HgfsPackGetattrRequestInt --
*
* Setup the getattr request, depending on the op version. When possible,
* we will issue the getattr using an existing open HGFS handle.
@@ -386,107 +462,34 @@ HgfsPackCommonattr(HgfsReq *req, // IN/OUT: request buffer
*/
static int
-HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer
- HgfsOp opUsed, // IN: Op to be used
- Bool allowHandleReuse, // IN: Can we use a handle?
- struct dentry *dentry, // IN: Dentry containing name
- HgfsAttrInfo *attr) // OUT: Attrs to update
+HgfsPackGetattrRequestInt(HgfsReq *req, // IN/OUT: Request buffer
+ HgfsOp opUsed, // IN: Op to be used
+ Bool allowHandleReuse, // IN: Can we use a handle?
+ HgfsSuperInfo *si, // IN: super block info
+ struct dentry *dentry, // IN: Optional dentry containing name/handle
+ HgfsAttrInfo *attr) // OUT: Attrs to update
{
size_t reqBufferSize;
size_t reqSize;
char *fileName = NULL;
uint32 *fileNameLength = NULL;
+ HgfsHandle handle = HGFS_INVALID_HANDLE;
int result = 0;
- ASSERT(attr);
- ASSERT(dentry);
- ASSERT(req);
+ ASSERT(attr != NULL);
+ ASSERT(req != NULL);
+ ASSERT(si != NULL);
- result = HgfsPackCommonattr(req,
- opUsed,
- allowHandleReuse,
- dentry->d_inode,
- &reqSize,
- &reqBufferSize,
- &fileName,
- &fileNameLength,
- attr);
- if (0 > result) {
- goto out;
+ if (allowHandleReuse) {
+ /* The dentry must be valid if the caller wants to use a file handle. */
+ ASSERT(dentry != NULL);
+ /* Errors are dropped getting the file handle, as we will use the name instead. */
+ (void)HgfsGetHandle(dentry->d_inode, 0, &handle);
}
- /* Avoid all this extra work when we're doing a getattr by handle. */
- if (fileName != NULL) {
-
- /* Build full name to send to server. */
- if (HgfsBuildPath(fileName, reqBufferSize,
- dentry) < 0) {
- LOG(4, (KERN_DEBUG "VMware hgfs: %s: build path failed\n", __func__));
- result = -EINVAL;
- goto out;
- }
- LOG(6, (KERN_DEBUG "VMware hgfs: %s: getting attrs for \"%s\"\n",
- __func__, fileName));
-
- /* Convert to CP name. */
- result = CPName_ConvertTo(fileName,
- reqBufferSize,
- fileName);
- if (result < 0) {
- LOG(4, (KERN_DEBUG "VMware hgfs: %s: CP conversion failed\n", __func__));
- result = -EINVAL;
- goto out;
- }
-
- *fileNameLength = result;
- }
-
- req->payloadSize = reqSize + result;
- result = 0;
-
-out:
- return result;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * HgfsPackGetattrRootRequest --
- *
- * Setup the getattr request for the root of the HGFS file system.
- *
- * When possible, we will issue the getattr using an existing open HGFS handle.
- *
- * Results:
- * Returns zero on success, or negative error on failure.
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-
-static int
-HgfsPackGetattrRootRequest(HgfsReq *req, // IN/OUT: Request buffer
- HgfsOp opUsed, // IN: Op to be used
- struct super_block *sb, // IN: Super block entry
- HgfsAttrInfo *attr) // OUT: Attrs to update
-{
- size_t reqBufferSize;
- size_t reqSize;
- char *fileName = NULL;
- uint32 *fileNameLength = NULL;
- int result = 0;
-
- ASSERT(attr);
- ASSERT(sb);
- ASSERT(req);
-
result = HgfsPackCommonattr(req,
opUsed,
- FALSE,
- NULL,
+ handle,
&reqSize,
&reqBufferSize,
&fileName,
@@ -498,12 +501,12 @@ HgfsPackGetattrRootRequest(HgfsReq *req, // IN/OUT: Request buffer
/* Avoid all this extra work when we're doing a getattr by handle. */
if (fileName != NULL) {
- HgfsSuperInfo *si = HGFS_SB_TO_COMMON(sb);
/* Build full name to send to server. */
- if (HgfsBuildRootPath(fileName,
+ if (HgfsBuildFullPath(fileName,
reqBufferSize,
- si) < 0) {
+ si,
+ dentry) < 0) {
LOG(4, (KERN_DEBUG "VMware hgfs: %s: build path failed\n", __func__));
result = -EINVAL;
goto out;
@@ -531,6 +534,7 @@ out:
return result;
}
+
/*
* Public function implementations.
*/
@@ -615,6 +619,10 @@ HgfsUnpackCommonAttr(HgfsReq *req, // IN: Reply packet
attrInfo->size = attrV2->size;
attrInfo->mask |= HGFS_ATTR_VALID_SIZE;
}
+ if (attrV2->mask & HGFS_ATTR_VALID_ALLOCATION_SIZE) {
+ attrInfo->allocSize = attrV2->allocationSize;
+ attrInfo->mask |= HGFS_ATTR_VALID_ALLOCATION_SIZE;
+ }
if (attrV2->mask & HGFS_ATTR_VALID_ACCESS_TIME) {
attrInfo->accessTime = attrV2->accessTime;
attrInfo->mask |= HGFS_ATTR_VALID_ACCESS_TIME;
@@ -721,6 +729,18 @@ HgfsCalcBlockSize(uint64 tsize)
#endif
+static inline int
+hgfs_timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
+{
+ if (lhs->tv_sec < rhs->tv_sec)
+ return -1;
+ if (lhs->tv_sec > rhs->tv_sec)
+ return 1;
+ return lhs->tv_nsec - rhs->tv_nsec;
+}
+
+
+
/*
*----------------------------------------------------------------------
*
@@ -749,7 +769,8 @@ HgfsSetInodeUidGid(struct inode *inode, // IN/OUT: Inode
* Use the stored uid and gid if we were given them at mount-time, or if
* the server didn't give us a uid or gid.
*/
- if (si->uidSet || (attr->mask & HGFS_ATTR_VALID_USERID) == 0) {
+ if ((si->mntFlags & HGFS_MNT_SET_UID) != 0 ||
+ (attr->mask & HGFS_ATTR_VALID_USERID) == 0) {
inode->i_uid = si->uid;
} else {
kuid_t attrUid = make_kuid(&init_user_ns, attr->userId);
@@ -765,7 +786,8 @@ HgfsSetInodeUidGid(struct inode *inode, // IN/OUT: Inode
LOG(6, (KERN_DEBUG "VMware hgfs: %s: inode uid %u\n",
__func__, from_kuid(&init_user_ns, inode->i_uid)));
}
- if (si->gidSet || (attr->mask & HGFS_ATTR_VALID_GROUPID) == 0) {
+ if ((si->mntFlags & HGFS_MNT_SET_GID) != 0 ||
+ (attr->mask & HGFS_ATTR_VALID_GROUPID) == 0) {
inode->i_gid = si->gid;
} else {
kgid_t attrGid = make_kgid(&init_user_ns, attr->groupId);
@@ -783,6 +805,74 @@ HgfsSetInodeUidGid(struct inode *inode, // IN/OUT: Inode
}
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsInodeWritable --
+ *
+ * Helper function for verifying if a file is under write access.
+ *
+ * Results:
+ * TRUE if file is writable, FALSE otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsInodeWritable(struct inode *inode) // IN: File we're writing to
+{
+ HgfsInodeInfo *iinfo;
+ struct list_head *cur;
+ Bool isWritable = FALSE;
+
+ iinfo = INODE_GET_II_P(inode);
+ /*
+ * Iterate over the open handles for this inode, and find if there
+ * is one that allows the write mode.
+ * Note, the mode is stored as incremented by one to prevent overload of
+ * the zero value.
+ */
+ spin_lock(&hgfsBigLock);
+ list_for_each(cur, &iinfo->files) {
+ HgfsFileInfo *finfo = list_entry(cur, HgfsFileInfo, list);
+
+ if (0 != (finfo->mode & (HGFS_OPEN_MODE_WRITE_ONLY + 1))) {
+ isWritable = TRUE;
+ break;
+ }
+ }
+ spin_unlock(&hgfsBigLock);
+
+ return isWritable;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsSafeToChange --
+ *
+ * Helper function for verifying if a file inode size and time fields is safe
+ * to update. It is deemed safe only if there is not an open writer to the file.
+ *
+ * Results:
+ * TRUE if safe to change inode, FALSE otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsSafeToChange(struct inode *inode) // IN: File we're writing to
+{
+ return !HgfsIsInodeWritable(inode);
+}
+
/*
*----------------------------------------------------------------------
@@ -808,13 +898,36 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
HgfsAttrInfo const *attr) // IN: New attrs
{
HgfsSuperInfo *si;
+ HgfsInodeInfo *iinfo;
+ loff_t fileSize = 0;
+ Bool fileSizeChanged = FALSE;
Bool needInvalidate = FALSE;
+ Bool isSafeToChange;
ASSERT(inode);
ASSERT(inode->i_sb);
ASSERT(attr);
si = HGFS_SB_TO_COMMON(inode->i_sb);
+ iinfo = INODE_GET_II_P(inode);
+
+ /*
+ * We do not want to update the file size from server or invalidate the inode
+ * for inodes open for write. We need to avoid races with the write page
+ * extending the file. This also will cause the server to possibly update the
+ * server side file's mod time too. For those situations we do not want to blindly
+ * go and invalidate the inode pages thus losing changes in flight and corrupting the
+ * file.
+ * We only need to invalidate the inode pages if the file has truly been modified
+ * on the server side by another server side application, not by our writes.
+ * If there are no writers it is safe to assume that newer mod time means the file
+ * changed on the server side underneath us.
+ */
+ isSafeToChange = HgfsIsSafeToChange(inode);
+
+ spin_lock(&inode->i_lock);
+
+ iinfo = INODE_GET_II_P(inode);
LOG(6, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: entered\n"));
HgfsSetFileType(inode, attr);
@@ -885,19 +998,30 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
/*
* Invalidate cached pages if we didn't receive the file size, or if it has
- * changed on the server.
+ * changed on the server, and no writes in flight.
*/
if (attr->mask & HGFS_ATTR_VALID_SIZE) {
- loff_t oldSize = compat_i_size_read(inode);
- inode->i_blocks = HgfsCalcBlockSize(attr->size);
- if (oldSize != attr->size) {
- if (oldSize < attr->size) {
- needInvalidate = TRUE;
+ fileSize = compat_i_size_read(inode);
+ LOG(8, (KERN_DEBUG "VMware hgfs: %s: srv size: %"FMT64"u, inode size: %Lu\n",
+ __func__, attr->size, fileSize));
+ if (fileSize != attr->size) {
+ if (iinfo->numWbPages == 0 && isSafeToChange) {
+ fileSizeChanged = needInvalidate = TRUE;
+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: new file "
+ "size: %"FMT64"u, old file size: %Lu\n", attr->size, fileSize));
+ compat_i_size_write(inode, attr->size);
}
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: new file "
- "size: %"FMT64"u, old file size: %Lu\n", attr->size, oldSize));
- compat_i_size_write(inode, attr->size);
}
+
+ fileSize = compat_i_size_read(inode);
+ if ((attr->mask & HGFS_ATTR_VALID_ALLOCATION_SIZE) != 0) {
+ inode->i_blocks = HgfsCalcBlockSize(attr->allocSize);
+ } else {
+ uint64 allocSize = ROUNDUP(fileSize, HGFS_BLOCKSIZE);
+ inode->i_blocks = HgfsCalcBlockSize(allocSize);
+ }
+ LOG(8, (KERN_DEBUG "VMware hgfs: %s: inode: size %Lu, blks %u\n",
+ __func__, fileSize, (uint32)inode->i_blocks));
} else {
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: did not "
"get file size\n"));
@@ -911,15 +1035,19 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
/*
* Invalidate cached pages if we didn't receive the modification time, or if
- * it has changed on the server.
+ * it has changed on the server and we don't have writes in flight and any open
+ * open writers.
*/
if (attr->mask & HGFS_ATTR_VALID_WRITE_TIME) {
HGFS_DECLARE_TIME(newTime);
HGFS_SET_TIME(newTime, attr->writeTime);
- if (!HGFS_EQUAL_TIME(newTime, inode->i_mtime)) {
+ if (hgfs_timespec_compare(&newTime, &inode->i_mtime) > 0 &&
+ iinfo->numWbPages == 0 &&
+ isSafeToChange) {
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: new mod "
"time: %ld:%lu, old mod time: %ld:%lu\n",
HGFS_PRINT_TIME(newTime), HGFS_PRINT_TIME(inode->i_mtime)));
+ needInvalidate = TRUE;
}
HGFS_SET_TIME(inode->i_mtime, attr->writeTime);
} else {
@@ -940,6 +1068,11 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
HGFS_SET_TIME(inode->i_ctime, HGFS_GET_CURRENT_TIME());
}
+ spin_unlock(&inode->i_lock);
+
+ if (fileSizeChanged) {
+ HGFS_TRUNCATE_PAGE_CACHE(inode, fileSize, attr->size);
+ }
/*
* Compare old size and write time with new size and write time. If there's
* a difference (or if we didn't get a new size or write time), the file
@@ -949,7 +1082,9 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: file has "
"changed on the server, invalidating pages.\n"));
compat_filemap_write_and_wait(inode->i_mapping);
- compat_invalidate_remote_inode(inode);
+ if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
+ invalidate_inode_pages2(inode->i_mapping);
+ }
}
}
@@ -1103,14 +1238,12 @@ HgfsSendGetattrRequest(HgfsReq *req, // IN: getattr request
/*
*----------------------------------------------------------------------
*
- * HgfsPrivateGetattrRoot --
+ * HgfsPrivateGetattrCmn --
*
- * The getattr for the root. Send a getattr request to the server
+ * The common getattr request. Send a getattr request to the server
* for the indicated remote name, and if it succeeds copy the
* results of the getattr into the provided HgfsAttrInfo.
*
- * fileName (of the root) will be set to a newly allocated string.
- *
* Results:
* Returns zero on success, or a negative error on failure.
*
@@ -1120,18 +1253,20 @@ HgfsSendGetattrRequest(HgfsReq *req, // IN: getattr request
*----------------------------------------------------------------------
*/
-int
-HgfsPrivateGetattrRoot(struct super_block *sb, // IN: Super block object
- HgfsAttrInfo *attr) // OUT: Attr to copy into
+static int
+HgfsPrivateGetattrCmn(HgfsSuperInfo *si, // IN: Super block info
+ struct dentry *dentry, // IN: Optional dentry containing name/handle
+ Bool allowHandleReuse, // IN: Use handle instead of name
+ HgfsAttrInfo *attr, // OUT: Attr to copy into
+ char **fileName) // OUT: Optional file name
{
HgfsReq *req;
HgfsOp opUsed;
int result = 0;
Bool doRetry;
- Bool allowHandleReuse = FALSE;
- ASSERT(sb);
- ASSERT(attr);
+ ASSERT(si != NULL);
+ ASSERT(attr != NULL);
req = HgfsGetNewRequest();
if (!req) {
@@ -1143,13 +1278,19 @@ HgfsPrivateGetattrRoot(struct super_block *sb, // IN: Super block object
retry:
opUsed = hgfsVersionGetattr;
- result = HgfsPackGetattrRootRequest(req, opUsed, sb, attr);
+
+ result = HgfsPackGetattrRequestInt(req,
+ opUsed,
+ allowHandleReuse,
+ si,
+ dentry,
+ attr);
if (result != 0) {
LOG(4, (KERN_DEBUG "VMware hgfs: %s: no attrs\n", __func__));
goto out;
}
- result = HgfsSendGetattrRequest(req, &doRetry, &allowHandleReuse, attr, NULL);
+ result = HgfsSendGetattrRequest(req, &doRetry, &allowHandleReuse, attr, fileName);
if (0 != result && doRetry) {
goto retry;
}
@@ -1163,6 +1304,40 @@ out:
/*
*----------------------------------------------------------------------
*
+ * HgfsPrivateGetattrRoot --
+ *
+ * The getattr for the root. Send a getattr request to the server
+ * for the indicated remote name, and if it succeeds copy the
+ * results of the getattr into the provided HgfsAttrInfo.
+ *
+ * fileName (of the root) will be set to a newly allocated string.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsPrivateGetattrRoot(struct super_block *sb, // IN: Super block object
+ HgfsAttrInfo *attr) // OUT: Attr to copy into
+{
+ HgfsSuperInfo *si;
+
+ ASSERT(sb != NULL);
+
+ si = HGFS_SB_TO_COMMON(sb);
+
+ return HgfsPrivateGetattrCmn(si, NULL, FALSE, attr, NULL);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* HgfsPrivateGetattr --
*
* Internal getattr routine. Send a getattr request to the server
@@ -1186,40 +1361,14 @@ HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name
HgfsAttrInfo *attr, // OUT: Attr to copy into
char **fileName) // OUT: pointer to allocated file name
{
- HgfsReq *req;
- HgfsOp opUsed;
- int result = 0;
- Bool doRetry;
- Bool allowHandleReuse = TRUE;
+ HgfsSuperInfo *si;
ASSERT(dentry);
ASSERT(dentry->d_sb);
- ASSERT(attr);
- req = HgfsGetNewRequest();
- if (!req) {
- LOG(4, (KERN_DEBUG "VMware hgfs: %s: out of memory "
- "while getting new request\n", __func__));
- result = -ENOMEM;
- goto out;
- }
-
-retry:
- opUsed = hgfsVersionGetattr;
- result = HgfsPackGetattrRequest(req, opUsed, allowHandleReuse, dentry, attr);
- if (result != 0) {
- LOG(4, (KERN_DEBUG "VMware hgfs: %s: no attrs\n", __func__));
- goto out;
- }
-
- result = HgfsSendGetattrRequest(req, &doRetry, &allowHandleReuse, attr, fileName);
- if (0 != result && doRetry) {
- goto retry;
- }
+ si = HGFS_SB_TO_COMMON(dentry->d_sb);
-out:
- HgfsFreeRequest(req);
- return result;
+ return HgfsPrivateGetattrCmn(si, dentry, TRUE, attr, fileName);
}
@@ -1248,117 +1397,61 @@ HgfsIget(struct super_block *sb, // IN: Superblock of this fs
ino_t ino, // IN: Inode number (optional)
HgfsAttrInfo const *attr) // IN: Attributes to create with
{
- HgfsInodeInfo *iinfo;
+ HgfsInodeAttrDesc iattrDesc;
+ HgfsSuperInfo *si;
struct inode *inode;
- Bool isFakeInodeNumber = FALSE;
+ ino_t hashedId = ino;
ASSERT(sb);
ASSERT(attr);
LOG(6, (KERN_DEBUG "VMware hgfs: HgfsIget: entered\n"));
+ si = HGFS_SB_TO_COMMON(sb);
+
+ /* Initialize the descriptor to use for finding an inode. */
+ iattrDesc.flags = 0;
+ iattrDesc.attr = attr;
+
+retry:
/* No inode number? Use what's in the attributes, or call iunique(). */
- if (ino == 0) {
+ if (hashedId == 0) {
/*
- * Let's find out if the inode number the server gave us is already
- * in use. It's kind of lame that we have to do this, but that's what
- * we get when certain files have valid inode numbers and certain ones
- * don't.
- *
- * XXX: Is this worth the value? We're mixing server-provided inode
- * numbers with our own randomly chosen inode numbers.
- *
- * XXX: This logic is also racy. After our call to ilookup(), it's
- * possible another caller came in and grabbed that inode number, which
- * will cause us to collide in iget() and step on their inode.
+ * Try and use the server supplied ID if possible otherwise
+ * failover to call iunique to generate one.
*/
- if (attr->mask & HGFS_ATTR_VALID_FILEID) {
- struct inode *oldInode;
-
- oldInode = ilookup(sb, attr->hostFileId);
- if (oldInode) {
- /*
- * If this inode's inode number was generated via iunique(), we
- * have a collision and cannot use the server's inode number.
- * Or, if the dentry is for a directory, we should not reuse the
- * inode in case there are two directory dentries referring to the
- * same inode. Otherwise, we should reuse this inode.
- *
- * Be careful of the following setting when resuing inodes:
- * host dir -> share name
- * C:/parent/ -> host1
- * C:/parent/child/ -> host2
- * /mnt/hgfs/host1/child and /mnt/hgfs/host2 are actually the
- * same directory in host. It also happens to the files in child.
- * Here, we should prevent the inode reusing because in Linux kernel
- * no inode can be pointed to by multiple directory entries; whereas
- * it is OK to do that for the files in /mnt/hgfs/child/.
- */
- iinfo = INODE_GET_II_P(oldInode);
- if (iinfo->isFakeInodeNumber ||
- attr->type == HGFS_FILE_TYPE_DIRECTORY) {
- LOG(6, ("VMware hgfs: %s: found existing iuniqued inode or "
- "directory inode %"FMT64"d, generating new one\n",
- __func__, attr->hostFileId));
- ino = iunique(sb, HGFS_RESERVED_INO);
- isFakeInodeNumber = TRUE;
- } else {
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsIget: found existing "
- "inode %"FMT64"d, reusing\n", attr->hostFileId));
- ino = attr->hostFileId;
- }
- iput(oldInode);
- } else {
- ino = attr->hostFileId;
- }
+ if ((si->mntFlags & HGFS_MNT_SERVER_INUM) != 0 &&
+ (attr->mask & HGFS_ATTR_VALID_FILEID) != 0) {
+ hashedId = HgfsUniqueidToIno(attr->hostFileId);
+
} else {
- /*
- * Get the next available inode number. There is a bit of a problem
- * with using iunique() in cases where HgfsIget was called to
- * instantiate an inode that's already in memory to a new dentry. In
- * such cases, we would like to get the old inode. But if we're
- * generating inode numbers with iunique(), we'll always have a new
- * inode number, thus we'll never get the old inode. This is
- * especially unfortunate when the old inode has some cached pages
- * attached to it that we won't be able to reuse.
- *
- * To mitigate this problem, whenever we use iunique() to generate an
- * inode number, we keep track of that fact in the inode. Then, when
- * we use ilookup() above to retrieve an inode, we only consider the
- * result a "collision" if the retrieved inode's inode number was set
- * via iunique(). Otherwise, we assume that we're reusing an inode
- * whose inode number was given to us by the server.
- */
- ino = iunique(sb, HGFS_RESERVED_INO);
- isFakeInodeNumber = TRUE;
+ iattrDesc.flags |= HGFS_INO_DESC_INO_FAKE;
}
}
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsIget: calling iget on inode number "
- "%lu\n", ino));
+ if ((iattrDesc.flags & HGFS_INO_DESC_INO_FAKE) != 0) {
+ hashedId = iunique(sb, HGFS_RESERVED_INO);
+ hashedId = HgfsUniqueidToIno(hashedId);
+ }
+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsIget: calling iget on inode number "
+ "%lu\n", hashedId));
- /* Now we have a good inode number, get the inode itself. */
- inode = HgfsGetInode(sb, ino);
+ /* Now try to find an inode for that number. */
+ inode = HgfsGetInode(sb, hashedId, &iattrDesc);
if (inode) {
-
- /*
- * On an allocation failure in read_super, the inode will have been
- * marked "bad". If it was, we certainly don't want to start playing with
- * the HgfsInodeInfo. So quietly put the inode back and fail.
- */
- if (is_bad_inode(inode)) {
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsIget: encountered bad inode\n"));
+ if ((iattrDesc.flags & HGFS_INO_DESC_INO_COLLISION) != 0) {
+ LOG(6, (KERN_DEBUG LGPFX "%s: collision using %lu\n", __func__, hashedId));
iput(inode);
- return NULL;
+ iattrDesc.flags &= ~HGFS_INO_DESC_INO_COLLISION;
+ iattrDesc.flags |= HGFS_INO_DESC_INO_FAKE;
+ goto retry;
}
-
- iinfo = INODE_GET_II_P(inode);
- if (attr->mask & HGFS_ATTR_VALID_FILEID) {
- iinfo->hostFileId = attr->hostFileId;
+ if ((inode->i_state & I_NEW) != 0) {
+ inode->i_ino = hashedId;
+ HgfsDoReadInode(inode);
+ unlock_new_inode(inode);
}
- iinfo->isFakeInodeNumber = isFakeInodeNumber;
- iinfo->isReferencedInode = TRUE;
HgfsChangeFileAttributes(inode, attr);
}
@@ -1370,6 +1463,109 @@ HgfsIget(struct super_block *sb, // IN: Superblock of this fs
/*
*-----------------------------------------------------------------------------
*
+ * HgfsInstantiateInode --
+ *
+ * Instantiate an inode.
+ * Look up or create a new inode based on the attributes and inode number
+ * (if supplied).
+ * If an inode number of zero may be specified, in which case HgfsIget will
+ * get one from the server or, barring that, from iunique().
+ *
+ * Results:
+ * Zero on success, negative error otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsInstantiateInode(struct super_block *sb, // IN: Super block
+ ino_t ino, // IN: Inode number (optional)
+ HgfsAttrInfo const *attr, // IN: Attributes to use (optional)
+ struct inode **inode) // OUT: instantiated inode
+{
+ int result = 0;
+
+ ASSERT(sb != NULL);
+ ASSERT(attr != NULL);
+ ASSERT(inode != NULL);
+
+ LOG(8, (KERN_DEBUG LGPFX "%s: entered\n", __func__));
+
+ /*
+ * Get the inode with this inode number and the attrs we got from
+ * the server.
+ */
+ *inode = HgfsIget(sb, ino, attr);
+ if (*inode == NULL) {
+ LOG(4, (KERN_DEBUG LGPFX "%s: error getting inode\n", __func__));
+ result = -ENOMEM;
+ }
+
+ return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsInstantiateDentry --
+ *
+ * Instantiate a dentry.
+ * Associate a dentry to a looked up or created inode.
+ *
+ * Results:
+ * Zero on success, negative error otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsInstantiateDentry(struct inode *inode, // IN: inode
+ Bool rootDentry, // IN: is root dentry or not
+ struct dentry **dentry) // IN/OUT: dentry to instantiate
+{
+ int result = 0;
+
+ ASSERT(dentry != NULL);
+ ASSERT(inode != NULL);
+
+ LOG(8, (KERN_DEBUG LGPFX "%s: instantiating dentry\n", __func__));
+
+ if (rootDentry) {
+ /*
+ * Now the initialization of the inode is complete we can create
+ * the root dentry which has flags initialized from the inode itself.
+ */
+ *dentry = d_make_root(inode);
+ if (*dentry == NULL) {
+ LOG(4, (KERN_WARNING LGPFX "%s: error make root dentry\n", __func__));
+ result = -ENOMEM;
+ goto exit;
+ }
+ }
+
+ ASSERT(*dentry != NULL);
+
+ HgfsDentryAgeReset(*dentry);
+ (*dentry)->d_op = &HgfsDentryOperations;
+ if (!rootDentry) {
+ d_instantiate(*dentry, inode);
+ }
+
+exit:
+ return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* HgfsInstantiateRoot --
*
* Gets the root dentry for a given super block.
@@ -1388,57 +1584,31 @@ int
HgfsInstantiateRoot(struct super_block *sb, // IN: Super block object
struct dentry **rootDentry) // OUT: Root dentry
{
- int result = -ENOMEM;
- struct inode *rootInode;
- struct dentry *tempRootDentry = NULL;
+ int result;
+ struct inode *rootInode = NULL;
struct HgfsAttrInfo rootDentryAttr;
- HgfsInodeInfo *iinfo;
- ASSERT(sb);
- ASSERT(rootDentry);
+ ASSERT(sb != NULL);
+ ASSERT(rootDentry != NULL);
- LOG(6, (KERN_DEBUG "VMware hgfs: %s: entered\n", __func__));
+ LOG(6, (KERN_DEBUG LGPFX "%s: entered\n", __func__));
- rootInode = HgfsGetInode(sb, HGFS_ROOT_INO);
- if (rootInode == NULL) {
- LOG(6, (KERN_DEBUG "VMware hgfs: %s: Could not get the root inode\n",
- __func__));
- goto exit;
- }
-
- /*
- * On an allocation failure in read_super, the inode will have been
- * marked "bad". If it was, we certainly don't want to start playing with
- * the HgfsInodeInfo. So quietly put the inode back and fail.
- */
- if (is_bad_inode(rootInode)) {
- LOG(6, (KERN_DEBUG "VMware hgfs: %s: encountered bad inode\n",
- __func__));
- goto exit;
- }
+ *rootDentry = NULL;
- LOG(8, (KERN_DEBUG "VMware hgfs: %s: retrieve root attrs\n", __func__));
+ LOG(8, (KERN_DEBUG LGPFX "%s: retrieve root attrs\n", __func__));
result = HgfsPrivateGetattrRoot(sb, &rootDentryAttr);
if (result) {
LOG(4, (KERN_WARNING "VMware hgfs: %s: Could not the root attrs\n", __func__));
goto exit;
}
- iinfo = INODE_GET_II_P(rootInode);
- iinfo->isFakeInodeNumber = FALSE;
- iinfo->isReferencedInode = TRUE;
-
- if (rootDentryAttr.mask & HGFS_ATTR_VALID_FILEID) {
- iinfo->hostFileId = rootDentryAttr.hostFileId;
+ result = HgfsInstantiateInode(sb, HGFS_ROOT_INO, &rootDentryAttr, &rootInode);
+ if (result) {
+ LOG(6, (KERN_DEBUG LGPFX "%s: Could not get the root inode\n", __func__));
+ goto exit;
}
- HgfsChangeFileAttributes(rootInode, &rootDentryAttr);
-
- /*
- * Now the initialization of the inode is complete we can create
- * the root dentry which has flags initialized from the inode itself.
- */
- tempRootDentry = d_make_root(rootInode);
+ result = HgfsInstantiateDentry(rootInode, TRUE, rootDentry);
/*
* d_make_root() does iput() on failure; if d_make_root() completes
* successfully then subsequent dput() will do iput() for us, so we
@@ -1446,25 +1616,12 @@ HgfsInstantiateRoot(struct super_block *sb, // IN: Super block object
*/
rootInode = NULL;
- if (tempRootDentry == NULL) {
- LOG(4, (KERN_WARNING "VMware hgfs: %s: Could not get "
- "root dentry\n", __func__));
- goto exit;
- }
-
- HgfsDentryAgeReset(tempRootDentry);
- tempRootDentry->d_op = &HgfsDentryOperations;
-
- *rootDentry = tempRootDentry;
- result = 0;
-
- LOG(6, (KERN_DEBUG "VMware hgfs: %s: finished\n", __func__));
exit:
if (result) {
iput(rootInode);
- dput(tempRootDentry);
- *rootDentry = NULL;
+ dput(*rootDentry);
}
+ LOG(6, (KERN_DEBUG LGPFX "%s: return %d\n", __func__, result));
return result;
}
@@ -1496,19 +1653,18 @@ HgfsInstantiate(struct dentry *dentry, // IN: Dentry to use
{
struct inode *inode;
HgfsAttrInfo newAttr;
+ int result;
ASSERT(dentry);
- LOG(8, (KERN_DEBUG "VMware hgfs: HgfsInstantiate: entered\n"));
+ LOG(8, (KERN_DEBUG LGPFX "%s: entered\n", __func__));
/* If no specified attributes, get them from the server. */
if (attr == NULL) {
- int error;
-
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInstantiate: issuing getattr\n"));
- error = HgfsPrivateGetattr(dentry, &newAttr, NULL);
- if (error) {
- return error;
+ LOG(8, (KERN_DEBUG LGPFX "%s: issuing getattr\n", __func__));
+ result = HgfsPrivateGetattr(dentry, &newAttr, NULL);
+ if (result) {
+ goto exit;
}
attr = &newAttr;
}
@@ -1517,19 +1673,58 @@ HgfsInstantiate(struct dentry *dentry, // IN: Dentry to use
* Get the inode with this inode number and the attrs we got from
* the server.
*/
- inode = HgfsIget(dentry->d_sb, ino, attr);
- if (!inode) {
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsInstantiate: out of memory "
- "getting inode\n"));
- return -ENOMEM;
+ result = HgfsInstantiateInode(dentry->d_sb, ino, attr, &inode);
+ if (result) {
+ goto exit;
}
/* Everything worked out, instantiate the dentry. */
- LOG(8, (KERN_DEBUG "VMware hgfs: HgfsInstantiate: instantiating dentry\n"));
- HgfsDentryAgeReset(dentry);
- dentry->d_op = &HgfsDentryOperations;
- d_instantiate(dentry, inode);
- return 0;
+ result = HgfsInstantiateDentry(inode, FALSE, &dentry);
+
+exit:
+ LOG(8, (KERN_DEBUG LGPFX "%s: return %d\n", __func__, result));
+ return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsBuildFullPath --
+ *
+ * Constructs the full path given the super info and optional dentry.
+ * This is a wrapper to the functions to build root path, if no dentry
+ * is supplied, and the general build path routine.
+ *
+ * Results:
+ * If non-negative, the length of the buffer written.
+ * Otherwise, an error code.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsBuildFullPath(char *buffer, // IN/OUT: Buffer to write into
+ size_t bufferLen, // IN: Size of buffer
+ HgfsSuperInfo *si, // IN: Super block info
+ struct dentry *dentry) // IN: Optional first dentry to walk
+{
+ int result = 0;
+
+ if (dentry == NULL) {
+ /* No dentry so we can construct only the root name. */
+ result = HgfsBuildRootPath(buffer,
+ bufferLen,
+ si);
+ } else {
+ result = HgfsBuildPath(buffer,
+ bufferLen,
+ dentry);
+ }
+ return result;
}
@@ -1550,7 +1745,7 @@ HgfsInstantiate(struct dentry *dentry, // IN: Dentry to use
*-----------------------------------------------------------------------------
*/
-int
+static int
HgfsBuildRootPath(char *buffer, // IN/OUT: Buffer to write into
size_t bufferLen, // IN: Size of buffer
HgfsSuperInfo *si) // IN: First dentry to walk
@@ -1714,7 +1909,7 @@ HgfsDentryAgeReset(struct dentry *dentry) // IN: Dentry whose age to reset
/*
*-----------------------------------------------------------------------------
*
- * HgfsDentryAgeReset --
+ * HgfsDentryAgeForce --
*
* Set the dentry's time to 0. This makes the dentry's age "too old" and
* forces subsequent HgfsRevalidates to go to the server for attributes.
@@ -2256,21 +2451,98 @@ HgfsSetUidGid(struct inode *parent, // IN: parent inode
*----------------------------------------------------------------------------
*/
-struct inode *
+static struct inode *
HgfsGetInode(struct super_block *sb, // IN: file system superblock object
- ino_t ino) // IN: inode number to assign to new inode
+ ino_t ino, // IN: inode number to assign to new inode
+ HgfsInodeAttrDesc *iattrDesc) // IN: Attributes to create with
{
- struct inode *inode;
+ return iget5_locked(sb, ino, HgfsFindInode, HgfsInitInode, iattrDesc);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsFindInode --
+ *
+ * This function is a callback used for comparisons between inodes.
+ *
+ * Results:
+ * 1 on success, 0 on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static int
+HgfsFindInode(struct inode *inode, // IN: compared inode
+ void *opaque) // IN: attribute data
+{
+ HgfsInodeAttrDesc *iattrDesc = opaque;
+ HgfsInodeInfo *iinfo = INODE_GET_II_P(inode);
+ int result = 1;
+
+ ASSERT(iattrDesc != NULL);
+
+ if (iinfo->hostFileId != iattrDesc->attr->hostFileId) {
+ /* Don't match inode with different unique Ids. */
+ result = 0;
+
+ } else if (iinfo->isFakeInodeNumber ||
+ iattrDesc->attr->type == HGFS_FILE_TYPE_DIRECTORY) {
+ iattrDesc->flags |= HGFS_INO_DESC_INO_COLLISION;
+ /* Deal with a collision and retry again. */
+ result = 1;
- inode = iget_locked(sb, ino);
- if (inode && (inode->i_state & I_NEW)) {
- HgfsDoReadInode(inode);
- unlock_new_inode(inode);
+ } else if (iattrDesc->attr->type != HgfsGetFileType(inode)) {
+ /* Don't match inodes of different types. */
+ result = 0;
+
+ } else if (is_bad_inode(inode)) {
+ result = 0;
}
- return inode;
+
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsInitInode --
+ *
+ * This function is a callback used to initialize a new struct inode.
+ *
+ * Results:
+ * Zero on success always.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static int
+HgfsInitInode(struct inode *inode, // IN: inode to init
+ void *opaque) // IN: attributes to init with
+{
+ HgfsInodeAttrDesc *iattrDesc = opaque;
+ HgfsInodeInfo *iinfo = INODE_GET_II_P(inode);
+
+ ASSERT(iattrDesc != NULL);
+
+ if ((iattrDesc->attr->mask & HGFS_ATTR_VALID_FILEID) != 0) {
+ iinfo->hostFileId = iattrDesc->attr->hostFileId;
+ }
+
+ iinfo->isFakeInodeNumber = (iattrDesc->flags & HGFS_INO_DESC_INO_FAKE) != 0;
+ return 0;
}
+
/*
*----------------------------------------------------------------------------
*
@@ -2292,7 +2564,7 @@ HgfsGetInode(struct super_block *sb, // IN: file system superblock object
*----------------------------------------------------------------------------
*/
-void
+static void
HgfsDoReadInode(struct inode *inode) // IN: Inode to initialize
{
HgfsInodeInfo *iinfo = INODE_GET_II_P(inode);
@@ -2307,9 +2579,8 @@ HgfsDoReadInode(struct inode *inode) // IN: Inode to initialize
*/
INODE_SET_II_P(inode, iinfo);
INIT_LIST_HEAD(&iinfo->files);
- iinfo->hostFileId = 0;
- iinfo->isReferencedInode = FALSE;
- iinfo->isFakeInodeNumber = FALSE;
iinfo->createdAndUnopened = FALSE;
+ iinfo->numWbPages = 0;
+ INIT_LIST_HEAD(&iinfo->listWbPages);
}
diff --git a/open-vm-tools/modules/linux/vmhgfs/fsutil.h b/open-vm-tools/modules/linux/vmhgfs/fsutil.h
index ff15b15f..754ad0dc 100644
--- a/open-vm-tools/modules/linux/vmhgfs/fsutil.h
+++ b/open-vm-tools/modules/linux/vmhgfs/fsutil.h
@@ -47,6 +47,7 @@ typedef struct HgfsAttrInfo {
HgfsOp requestType;
HgfsAttrValid mask;
HgfsFileType type; /* File type */
+ uint64 allocSize; /* Disk allocation size (in bytes) */
uint64 size; /* File size (in bytes) */
uint64 accessTime; /* Time of last access */
uint64 writeTime; /* Time of last write */
@@ -63,6 +64,44 @@ typedef struct HgfsAttrInfo {
} HgfsAttrInfo;
+/*
+ * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
+ * so that it will fit.
+ * Note, this is taken from CIFS so we apply the same algorithm.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+/*
+ * We use hash_64 to convert the value to 31 bits, and
+ * then add 1, to ensure that we don't end up with a 0 as the value.
+ */
+#if BITS_PER_LONG == 64
+static inline ino_t
+HgfsUniqueidToIno(uint64 fileid)
+{
+ return (ino_t)fileid;
+}
+#else
+#include <linux/hash.h>
+
+static inline ino_t
+HgfsUniqueidToIno(uint64 fileid)
+{
+ return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
+}
+#endif
+
+#else
+static inline ino_t
+HgfsUniqueidToIno(uint64 fileid)
+{
+ ino_t ino = (ino_t) fileid;
+ if (sizeof(ino_t) < sizeof(uint64)) {
+ ino ^= fileid >> (sizeof(uint64)-sizeof(ino_t)) * 8;
+ }
+ return ino;
+}
+#endif
+
/* Public functions (with respect to the entire module). */
int HgfsUnpackCommonAttr(HgfsReq *req,
HgfsAttrInfo *attr);
@@ -97,8 +136,6 @@ void HgfsSetUidGid(struct inode *parent,
struct dentry *dentry,
kuid_t uid,
kgid_t gid);
-struct inode *HgfsGetInode(struct super_block *sb, ino_t ino);
-void HgfsDoReadInode(struct inode *inode);
#endif // _HGFS_DRIVER_FSUTIL_H_
diff --git a/open-vm-tools/modules/linux/vmhgfs/inode.c b/open-vm-tools/modules/linux/vmhgfs/inode.c
index 77b16691..a600c0e9 100644
--- a/open-vm-tools/modules/linux/vmhgfs/inode.c
+++ b/open-vm-tools/modules/linux/vmhgfs/inode.c
@@ -68,6 +68,20 @@
#define hgfs_d_count(dentry) atomic_read(&dentry->d_count)
#endif
+#if defined VMW_DALIAS_319 || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+/*
+ * Linux Kernel versions that are version 3.19 and newer or are compatible
+ * by having the d_alias field moved into a union backported.
+ */
+#define hgfs_d_alias() d_u.d_alias
+#else
+/*
+ * Kernel versions that are not 3.19 version compatible or are just older will
+ * use the d_alias field directly.
+ */
+#define hgfs_d_alias() d_alias
+#endif
+
/* Private functions. */
static int HgfsDelete(struct inode *dir,
struct dentry *dentry,
@@ -1552,9 +1566,14 @@ retry:
*
* XXX: I think old servers will send -EPERM here. Is this entirely
* safe?
+ * We can receive EACCES or EPERM if we don't have the correct
+ * permission on the source file. So lets not assume that we have
+ * a target and only clear the target if there is one.
*/
- if (!secondAttempt) {
+ if (!secondAttempt && newDentry->d_inode != NULL) {
secondAttempt = TRUE;
+ LOG(4, (KERN_DEBUG "VMware hgfs: %s:clear target RO mode %8x\n",
+ __func__, newDentry->d_inode->i_mode));
result = HgfsClearReadOnly(newDentry);
if (result == 0) {
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: file is no "
@@ -1564,8 +1583,8 @@ retry:
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: failed to remove "
"read-only property\n"));
} else {
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: second attempt at "
- "rename failed\n"));
+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: second attempt or "
+ "no target failed\n"));
}
} else if (0 != result) {
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: failed with result %d\n", result));
@@ -1917,7 +1936,7 @@ HgfsPermission(struct inode *inode,
p,
#endif
&inode->i_dentry,
- d_alias) {
+ hgfs_d_alias()) {
int dcount = hgfs_d_count(dentry);
if (dcount) {
LOG(4, ("Found %s %d \n", dentry->d_name.name, dcount));
@@ -1970,7 +1989,7 @@ HgfsPermission(struct inode *inode,
/* Find a dentry with valid d_count. Refer bug 587879. */
list_for_each(pos, &inode->i_dentry) {
int dcount;
- struct dentry *dentry = list_entry(pos, struct dentry, d_alias);
+ struct dentry *dentry = list_entry(pos, struct dentry, hgfs_d_alias());
dcount = hgfs_d_count(dentry);
if (dcount) {
LOG(4, ("Found %s %d \n", (dentry)->d_name.name, dcount));
@@ -2059,7 +2078,6 @@ HgfsSetattr(struct dentry *dentry, // IN: File to set attributes of
ASSERT(dentry);
ASSERT(dentry->d_inode);
- ASSERT(dentry->d_inode->i_mapping);
ASSERT(dentry->d_sb);
ASSERT(iattr);
@@ -2086,6 +2104,7 @@ HgfsSetattr(struct dentry *dentry, // IN: File to set attributes of
* modify the file size or change the last write time.
*/
if (iattr->ia_valid & ATTR_SIZE || iattr->ia_valid & ATTR_MTIME) {
+ ASSERT(dentry->d_inode->i_mapping);
compat_filemap_write_and_wait(dentry->d_inode->i_mapping);
}
diff --git a/open-vm-tools/modules/linux/vmhgfs/module.h b/open-vm-tools/modules/linux/vmhgfs/module.h
index 9c123323..b673dc17 100644
--- a/open-vm-tools/modules/linux/vmhgfs/module.h
+++ b/open-vm-tools/modules/linux/vmhgfs/module.h
@@ -45,7 +45,7 @@
/* Logging stuff. */
#ifdef VMX86_DEVEL
extern int LOGLEVEL_THRESHOLD;
-
+#define LGPFX "VMware hgfs: "
#define LOG(level, args) ((void) (LOGLEVEL_THRESHOLD >= (level) ? (printk args) : 0))
#else
#define LOG(level, args)
@@ -84,6 +84,17 @@ typedef gid_t kgid_t;
#define make_kgid(_ns, _gid) (_gid)
#endif
+/*
+ * Since the f_dentry disappeared we do this locally.
+ * It is used quite extensively and only one other driver
+ * is affected by this so it is done locally and not
+ * as part of the common compat_fs.h includes.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+#ifndef f_dentry
+#define f_dentry f_path.dentry
+#endif
+#endif
#define HGFS_SET_SB_TO_COMMON(sb, common) do { (sb)->s_fs_info = (common); } while (0)
#define HGFS_SB_TO_COMMON(sb) ((HgfsSuperInfo *)(sb)->s_fs_info)
@@ -119,17 +130,20 @@ typedef gid_t kgid_t;
#define FILE_SET_FI_P(file, info) do { (file)->private_data = info; } while (0)
#define FILE_GET_FI_P(file) ((HgfsFileInfo *)(file)->private_data)
+#define HGFS_MNT_SET_UID (1 << 0) /* Was the UID specified at mount-time? */
+#define HGFS_MNT_SET_GID (1 << 1) /* Was the GID specified at mount-time? */
+#define HGFS_MNT_SERVER_INUM (1 << 2) /* Use inode numbers from the server? */
+
/* Data kept in each superblock in sb->u. */
typedef struct HgfsSuperInfo {
kuid_t uid; /* UID of user who mounted this fs. */
kgid_t gid; /* GID of user who mounted this fs. */
- Bool uidSet; /* Was the UID specified at mount-time? */
- Bool gidSet; /* Was the GID specified at mount-time? */
mode_t fmask; /* File permission mask. */
mode_t dmask; /* Directory permission mask. */
uint32 ttl; /* Maximum dentry age (in ticks). */
char *shareName; /* Mounted share name. */
size_t shareNameLen; /* To avoid repeated strlen() calls. */
+ uint32 mntFlags; /* HGFS mount flags */
} HgfsSuperInfo;
/*
@@ -148,8 +162,12 @@ typedef struct HgfsInodeInfo {
/* Is this a fake inode created in HgfsCreate that has yet to be opened? */
Bool createdAndUnopened;
- /* Is this inode referenced by HGFS? (needed by HgfsInodeLookup()) */
- Bool isReferencedInode;
+ /*
+ * The number of write back pages to the file which is tracked so any
+ * concurrent file validations such as reads will not invalidate the cache.
+ */
+ unsigned long numWbPages;
+ struct list_head listWbPages;
/* List of open files for this inode. */
struct list_head files;
diff --git a/open-vm-tools/modules/linux/vmhgfs/page.c b/open-vm-tools/modules/linux/vmhgfs/page.c
index 56f98621..9e31c12d 100644
--- a/open-vm-tools/modules/linux/vmhgfs/page.c
+++ b/open-vm-tools/modules/linux/vmhgfs/page.c
@@ -44,8 +44,34 @@
#include "inode.h"
#include "vm_assert.h"
#include "vm_basic_types.h"
-#include "hgfsTransport.h"
+#include "vm_basic_defs.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+#define HGFS_SM_MB_BEFORE smp_mb__before_atomic
+#define HGFS_SM_MB_AFTER smp_mb__after_atomic
+#else
+/*
+ * Fedora 21 backported some of the atomic primitives so
+ * we test if they are defined and use them otherwise fallback
+ * to the older variants.
+ */
+#ifdef smp_mb__before_atomic
+#define HGFS_SM_MB_BEFORE smp_mb__before_atomic
+#else
+#define HGFS_SM_MB_BEFORE smp_mb__before_clear_bit
+#endif
+#ifdef smp_mb__after_atomic
+#define HGFS_SM_MB_AFTER smp_mb__after_atomic
+#else
+#define HGFS_SM_MB_AFTER smp_mb__after_clear_bit
+#endif
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+#define HGFS_PAGE_FILE_INDEX(page) page_file_index(page)
+#else
+#define HGFS_PAGE_FILE_INDEX(page) ((page)->index)
+#endif
/* Private functions. */
static int HgfsDoWrite(HgfsHandle handle,
@@ -67,13 +93,17 @@ static int HgfsDoWritepage(HgfsHandle handle,
static int HgfsDoWriteBegin(struct file *file,
struct page *page,
unsigned pageFrom,
- unsigned pageTo);
+ unsigned pageTo,
+ Bool canRetry,
+ Bool *doRetry);
static int HgfsDoWriteEnd(struct file *file,
struct page *page,
unsigned pageFrom,
unsigned pageTo,
loff_t writeTo,
unsigned copied);
+static void HgfsDoExtendFile(struct inode *inode,
+ loff_t writeTo);
/* HGFS address space operations. */
static int HgfsReadpage(struct file *file,
@@ -129,6 +159,33 @@ struct address_space_operations HgfsAddressSpaceOperations = {
.set_page_dirty = __set_page_dirty_nobuffers,
};
+enum {
+ PG_BUSY = 0,
+};
+
+typedef struct HgfsWbPage {
+ struct list_head wb_list; /* Defines state of page: */
+ struct page *wb_page; /* page to read in/write out */
+ pgoff_t wb_index; /* Offset >> PAGE_CACHE_SHIFT */
+ struct kref wb_kref; /* reference count */
+ unsigned long wb_flags;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
+ wait_queue_head_t wb_queue;
+#endif
+} HgfsWbPage;
+
+static void HgfsInodePageWbAdd(struct inode *inode,
+ struct page *page);
+static void HgfsInodePageWbRemove(struct inode *inode,
+ struct page *page);
+static Bool HgfsInodePageWbFind(struct inode *inode,
+ struct page *page);
+static void HgfsWbRequestDestroy(HgfsWbPage *req);
+static Bool HgfsCheckReadModifyWrite(struct file *file,
+ struct page *page,
+ unsigned int pageFrom,
+ unsigned int pageTo);
+
/*
* Private functions.
@@ -267,11 +324,11 @@ HgfsDoRead(HgfsHandle handle, // IN: Handle for this file
goto out;
}
- if (!actualSize) {
+ result = actualSize;
+ if (actualSize == 0) {
/* We got no bytes. */
LOG(6, (KERN_WARNING "VMware hgfs: HgfsDoRead: server returned "
"zero\n"));
- result = actualSize;
goto out;
}
@@ -284,8 +341,7 @@ HgfsDoRead(HgfsHandle handle, // IN: Handle for this file
actualSize));
kunmap(dataPacket[0].page);
}
- result = actualSize;
- break;
+ break;
case -EPROTO:
/* Retry with older version(s). Set globally. */
@@ -563,7 +619,7 @@ HgfsDoReadpage(HgfsHandle handle, // IN: Handle to use for reading
unsigned pageTo) // IN: Where to stop reading
{
int result = 0;
- loff_t curOffset = ((loff_t)page->index << PAGE_CACHE_SHIFT) + pageFrom;
+ loff_t curOffset = ((loff_t)HGFS_PAGE_FILE_INDEX(page) << PAGE_CACHE_SHIFT) + pageFrom;
size_t nextCount, remainingCount = pageTo - pageFrom;
HgfsDataPacket dataPacket[1];
@@ -616,6 +672,7 @@ HgfsDoReadpage(HgfsHandle handle, // IN: Handle to use for reading
result = 0;
out:
+ compat_unlock_page(page);
return result;
}
@@ -623,7 +680,7 @@ HgfsDoReadpage(HgfsHandle handle, // IN: Handle to use for reading
/*
*-----------------------------------------------------------------------------
*
- * HgfsDoWritepage --
+ * HgfsDoWritepageInt --
*
* Writes out a single page, using the specified handle and page offsets.
* At the time of writing, HGFS_IO_MAX == PAGE_CACHE_SIZE, so we could
@@ -631,22 +688,8 @@ HgfsDoReadpage(HgfsHandle handle, // IN: Handle to use for reading
* above assumption is ever broken, it's nice that this will continue to
* "just work".
*
- * A quick note about appending to files. Before HGFS used the page cache,
- * an HgfsWrite examined a file's f_flags and added HGFS_WRITE_APPEND to
- * the write packet if the file was opened with O_APPEND. This causes the
- * server to reopen the fd with O_APPEND so that writes will append to the
- * end.
- *
- * In the page cache world, this won't work because we may have arrived at
- * this function via writepage(), which doesn't give us a particular file
- * and thus we don't know if we should be appending or not. In fact, the
- * generic write path employed by the page cache handles files with O_APPEND
- * set by moving the file offset to the result of i_size_read(). So we
- * shouldn't ever need to set HGFS_WRITE_APPEND, as now we will handle all
- * write appends, instead of telling the server to do it for us.
- *
* Results:
- * Zero on success, non-zero on error.
+ * Number of bytes copied on success, negative error on error.
*
* Side effects:
* None.
@@ -655,13 +698,13 @@ HgfsDoReadpage(HgfsHandle handle, // IN: Handle to use for reading
*/
static int
-HgfsDoWritepage(HgfsHandle handle, // IN: Handle to use for writing
- struct page *page, // IN: Page containing data to write
- unsigned pageFrom, // IN: Beginning page offset
- unsigned pageTo) // IN: Ending page offset
+HgfsDoWritepageInt(HgfsHandle handle, // IN: Handle to use for writing
+ struct page *page, // IN: Page containing data to write
+ unsigned pageFrom, // IN: Beginning page offset
+ unsigned pageTo) // IN: Ending page offset
{
int result = 0;
- loff_t curOffset = ((loff_t)page->index << PAGE_CACHE_SHIFT) + pageFrom;
+ loff_t curOffset = ((loff_t)HGFS_PAGE_FILE_INDEX(page) << PAGE_CACHE_SHIFT) + pageFrom;
size_t nextCount;
size_t remainingCount = pageTo - pageFrom;
struct inode *inode;
@@ -689,23 +732,81 @@ HgfsDoWritepage(HgfsHandle handle, // IN: Handle to use for writing
if (result < 0) {
LOG(4, (KERN_WARNING "VMware hgfs: %s: write error %d\n",
__func__, result));
- goto out;
+ goto exit;
}
remainingCount -= result;
curOffset += result;
pageFrom += result;
/* Update the inode's size now rather than waiting for a revalidate. */
- if (curOffset > compat_i_size_read(inode)) {
- compat_i_size_write(inode, curOffset);
- }
+ HgfsDoExtendFile(inode, curOffset);
} while ((result > 0) && (remainingCount > 0));
+exit:
+ if (result >= 0) {
+ result = pageTo - pageFrom - remainingCount;
+ }
+ return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsDoWritepage --
+ *
+ * Writes out a single page, using the specified handle and page offsets.
+ * At the time of writing, HGFS_IO_MAX == PAGE_CACHE_SIZE, so we could
+ * avoid the do {} while() and just write the page as is, but in case the
+ * above assumption is ever broken, it's nice that this will continue to
+ * "just work".
+ *
+ * A quick note about appending to files. Before HGFS used the page cache,
+ * an HgfsWrite examined a file's f_flags and added HGFS_WRITE_APPEND to
+ * the write packet if the file was opened with O_APPEND. This causes the
+ * server to reopen the fd with O_APPEND so that writes will append to the
+ * end.
+ *
+ * In the page cache world, this won't work because we may have arrived at
+ * this function via writepage(), which doesn't give us a particular file
+ * and thus we don't know if we should be appending or not. In fact, the
+ * generic write path employed by the page cache handles files with O_APPEND
+ * set by moving the file offset to the result of i_size_read(). So we
+ * shouldn't ever need to set HGFS_WRITE_APPEND, as now we will handle all
+ * write appends, instead of telling the server to do it for us.
+ *
+ * Results:
+ * Zero on success, non-zero on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsDoWritepage(HgfsHandle handle, // IN: Handle to use for writing
+ struct page *page, // IN: Page containing data to write
+ unsigned pageFrom, // IN: Beginning page offset
+ unsigned pageTo) // IN: Ending page offset
+{
+ int result = 0;
+
+ LOG(4, (KERN_WARNING "VMware hgfs: %s: start writes at %u to %u\n",
+ __func__, pageFrom, pageTo));
+
+ result = HgfsDoWritepageInt(handle, page, pageFrom, pageTo);
+ if (result < 0) {
+ goto exit;
+ }
+
+ HgfsInodePageWbRemove(page->mapping->host, page);
+
result = 0;
- LOG(4, (KERN_WARNING "VMware hgfs: %s: end writes at %Lu rem %zu\n",
- __func__, curOffset, remainingCount));
+ SetPageUptodate(page);
- out:
+exit:
+ LOG(4, (KERN_WARNING "VMware hgfs: %s: return %d\n", __func__, result));
return result;
}
@@ -748,13 +849,12 @@ HgfsReadpage(struct file *file, // IN: File to read from
ASSERT(page);
handle = FILE_GET_FI_P(file)->handle;
- LOG(6, (KERN_WARNING "VMware hgfs: HgfsReadPage: reading from handle %u\n",
- handle));
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: reading from handle %u\n",
+ __func__, handle));
page_cache_get(page);
result = HgfsDoReadpage(handle, page, 0, PAGE_CACHE_SIZE);
page_cache_release(page);
- compat_unlock_page(page);
return result;
}
@@ -787,6 +887,7 @@ HgfsWritepage(struct page *page, // IN: Page to write from
HgfsHandle handle;
int result;
pgoff_t lastPageIndex;
+ pgoff_t pageIndex;
loff_t currentFileSize;
unsigned to = PAGE_CACHE_SIZE;
@@ -819,11 +920,12 @@ HgfsWritepage(struct page *page, // IN: Page to write from
*/
currentFileSize = compat_i_size_read(inode);
lastPageIndex = currentFileSize >> PAGE_CACHE_SHIFT;
+ pageIndex = HGFS_PAGE_FILE_INDEX(page);
LOG(4, (KERN_WARNING "VMware hgfs: %s: file size lpi %lu pi %lu\n",
- __func__, lastPageIndex, page->index));
- if (page->index > lastPageIndex) {
+ __func__, lastPageIndex, pageIndex));
+ if (pageIndex > lastPageIndex) {
goto exit;
- } else if (page->index == lastPageIndex) {
+ } else if (pageIndex == lastPageIndex) {
to = currentFileSize & (PAGE_CACHE_SIZE - 1);
if (to == 0) {
goto exit;
@@ -888,30 +990,33 @@ static int
HgfsDoWriteBegin(struct file *file, // IN: File to be written
struct page *page, // IN: Page to be written
unsigned pageFrom, // IN: Starting page offset
- unsigned pageTo) // IN: Ending page offset
+ unsigned pageTo, // IN: Ending page offset
+ Bool canRetry, // IN: can we retry write
+ Bool *doRetry) // OUT: set to retry if necessary
{
ASSERT(page);
LOG(6, (KERN_DEBUG "VMware hgfs: %s: off %Lu: %u to %u\n", __func__,
- (loff_t)page->index << PAGE_CACHE_SHIFT, pageFrom, pageTo));
-
- if (!PageUptodate(page)) {
- /*
- * If we are doing a partial write into a new page (beyond end of
- * file), then intialize it. This allows other writes to this page
- * to accumulate before we need to write it to the server.
- */
- if (pageTo - pageFrom != PAGE_CACHE_SIZE) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
- zero_user_segments(page, 0, pageFrom, pageTo, PAGE_CACHE_SIZE);
-#else
- void *kaddr = compat_kmap_atomic(page);
- memset(kaddr, 0, pageFrom);
- memset(kaddr + pageTo, 0, PAGE_CACHE_SIZE - pageTo);
- flush_dcache_page(page);
- compat_kunmap_atomic(kaddr);
-#endif
+ (loff_t)HGFS_PAGE_FILE_INDEX(page) << PAGE_CACHE_SHIFT, pageFrom, pageTo));
+
+ if (canRetry && HgfsCheckReadModifyWrite(file, page, pageFrom, pageTo)) {
+ HgfsHandle readHandle;
+ int result;
+ result = HgfsGetHandle(page->mapping->host,
+ HGFS_OPEN_MODE_READ_ONLY + 1,
+ &readHandle);
+ if (result == 0) {
+ /*
+ * We have a partial page write and thus require non-written part if the page
+ * is to contain valid data.
+ * A read of the page of the valid file data will set the page up to date.
+ * If it fails the page will not be set up to date and the write end will write
+ * the data out immediately (synchronously effectively).
+ */
+ result = HgfsDoReadpage(readHandle, page, 0, PAGE_CACHE_SIZE);
+ *doRetry = TRUE;
}
+ LOG(6, (KERN_DEBUG "VMware hgfs: %s: HgfsReadpage result %d\n", __func__, result));
}
LOG(6, (KERN_DEBUG "VMware hgfs: %s: returns 0\n", __func__));
@@ -944,7 +1049,8 @@ HgfsPrepareWrite(struct file *file, // IN: File to be written
unsigned pageFrom, // IN: Beginning page offset
unsigned pageTo) // IN: Ending page offset
{
- return HgfsDoWriteBegin(file, page, pageFrom, pageTo);
+ Bool dummyCanRetry = FALSE;
+ return HgfsDoWriteBegin(file, page, pageFrom, pageTo, FALSE, &dummyCanRetry);
}
#else
@@ -984,28 +1090,37 @@ HgfsWriteBegin(struct file *file, // IN: File to be written
unsigned pageTo = pageFrom + len;
struct page *page;
int result;
+ Bool canRetry = TRUE;
+ Bool doRetry;
LOG(6, (KERN_WARNING "VMware hgfs: %s: (%s/%s(%ld), %u@%lld)\n",
__func__, file->f_dentry->d_parent->d_name.name,
file->f_dentry->d_name.name,
mapping->host->i_ino, len, (long long) pos));
- page = compat_grab_cache_page_write_begin(mapping, index, flags);
- if (page == NULL) {
- result = -ENOMEM;
- goto exit;
- }
- *pagePtr = page;
+ do {
+ doRetry = FALSE;
+ page = compat_grab_cache_page_write_begin(mapping, index, flags);
+ if (page == NULL) {
+ result = -ENOMEM;
+ goto exit;
+ }
- LOG(6, (KERN_DEBUG "VMware hgfs: %s: file size %Lu @ %Lu page %u to %u\n", __func__,
- (loff_t)compat_i_size_read(page->mapping->host),
- (loff_t)page->index << PAGE_CACHE_SHIFT,
- pageFrom, pageTo));
+ LOG(6, (KERN_DEBUG "VMware hgfs: %s: file size %Lu @ %Lu page %u to %u\n", __func__,
+ (loff_t)compat_i_size_read(page->mapping->host),
+ (loff_t)HGFS_PAGE_FILE_INDEX(page) << PAGE_CACHE_SHIFT,
+ pageFrom, pageTo));
- result = HgfsDoWriteBegin(file, page, pageFrom, pageTo);
- ASSERT(result == 0);
+ result = HgfsDoWriteBegin(file, page, pageFrom, pageTo, canRetry, &doRetry);
+ ASSERT(result == 0);
+ canRetry = FALSE;
+ if (doRetry) {
+ page_cache_release(page);
+ }
+ } while (doRetry);
exit:
+ *pagePtr = page;
LOG(6, (KERN_DEBUG "VMware hgfs: %s: return %d\n", __func__, result));
return result;
}
@@ -1015,6 +1130,144 @@ exit:
/*
*-----------------------------------------------------------------------------
*
+ * HgfsDoExtendFile --
+ *
+ * Helper function for extending a file size.
+ *
+ * This function updates the inode->i_size, under the inode lock.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsDoExtendFile(struct inode *inode, // IN: File we're writing to
+ loff_t writeTo) // IN: Offset we're written to
+{
+ loff_t currentFileSize;
+
+ spin_lock(&inode->i_lock);
+ currentFileSize = compat_i_size_read(inode);
+
+ if (writeTo > currentFileSize) {
+ compat_i_size_write(inode, writeTo);
+ }
+ spin_unlock(&inode->i_lock);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsZeroUserSegments --
+ *
+ * Wrapper function for setting a page's segments.
+ *
+ * This function updates the inode->i_size, under the inode lock.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsZeroUserSegments(struct page *page, // IN: Page we're writing to
+ unsigned int start1, // IN: segment 1 start
+ unsigned int end1, // IN: segment 1 end
+ unsigned int start2, // IN: segment 2 start
+ unsigned int end2) // IN: segment 2 end
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+ zero_user_segments(page, start1, end1, start2, end2);
+#else
+ void *kaddr = compat_kmap_atomic(page);
+ if (end1 > start1) {
+ memset(kaddr + start1, 0, end1 - start1);
+ }
+ if (end2 > start2) {
+ memset(kaddr + start2, 0, end2 - start2);
+ }
+ compat_kunmap_atomic(kaddr);
+ flush_dcache_page(page);
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsZeroUserSegments --
+ *
+ * Wrapper function for zeroing a page's segments.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsZeroUserSegment(struct page *page, // IN: Page we're writing to
+ unsigned int start, // IN: segment 1 start
+ unsigned int end) // IN: segment 1 end
+{
+ HgfsZeroUserSegments(page, start, end, 0, 0);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsGetPageLength --
+ *
+ * Helper function for finding the extent of valid file data in a page.
+ *
+ * Results:
+ * The page valid data length.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static unsigned int
+HgfsGetPageLength(struct page *page) // IN: Page we're writing to
+{
+ loff_t currentFileSize;
+ unsigned int pageLength = 0;
+
+ currentFileSize = compat_i_size_read(page->mapping->host);
+ if (currentFileSize > 0) {
+ pgoff_t pageIndex = HGFS_PAGE_FILE_INDEX(page);
+ pgoff_t fileSizeIndex = (currentFileSize - 1) >> PAGE_CACHE_SHIFT;
+
+ if (pageIndex < fileSizeIndex) {
+ pageLength = PAGE_CACHE_SIZE;
+ } else if (pageIndex == fileSizeIndex) {
+ pageLength = ((currentFileSize - 1) & ~PAGE_CACHE_MASK) + 1;
+ }
+ }
+
+ return pageLength;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* HgfsDoWriteEnd --
*
* Helper function for HgfsWriteEnd.
@@ -1039,13 +1292,11 @@ HgfsDoWriteEnd(struct file *file, // IN: File we're writing to
loff_t writeTo, // IN: File position to write to
unsigned copied) // IN: Number of bytes copied to the page
{
- loff_t currentFileSize;
struct inode *inode;
ASSERT(file);
ASSERT(page);
inode = page->mapping->host;
- currentFileSize = compat_i_size_read(inode);
LOG(6, (KERN_WARNING "VMware hgfs: %s: (%s/%s(%ld), from %u to %u@%lld => %u)\n",
__func__, file->f_dentry->d_parent->d_name.name,
@@ -1057,14 +1308,45 @@ HgfsDoWriteEnd(struct file *file, // IN: File we're writing to
* as up to date if it turns out that we're extending the file.
*/
if (!PageUptodate(page)) {
- SetPageUptodate(page);
+ unsigned int pageLength = HgfsGetPageLength(page);
+
+ if (pageLength == 0) {
+ /* No file valid data in this page. Zero unwritten segments only. */
+ HgfsZeroUserSegments(page, 0, pageFrom, pageTo, PAGE_CACHE_SIZE);
+ SetPageUptodate(page);
+ } else if (pageTo >= pageLength) {
+ /* Some file valid data in this page. Zero unwritten segments only. */
+ HgfsZeroUserSegment(page, pageTo, PAGE_CACHE_SIZE);
+ if (pageTo == 0) {
+ /* Overwritten all file valid data in this page. So the page is uptodate. */
+ SetPageUptodate(page);
+ }
+ } else {
+ /* Overwriting part of the valid file data. */
+ HgfsZeroUserSegment(page, pageLength, PAGE_CACHE_SIZE);
+ }
}
- if (writeTo > currentFileSize) {
- compat_i_size_write(inode, writeTo);
+
+ if (!PageUptodate(page)) {
+ HgfsHandle handle = FILE_GET_FI_P(file)->handle;
+ int result;
+
+ /* Do a synchronous write since we have a partial page write of data. */
+ result = HgfsDoWritepageInt(handle, page, pageFrom, pageTo);
+ if (result == 0) {
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: sync write return %d\n", __func__, result));
+ }
+ } else {
+ /* Page to write contains all valid data. */
+ set_page_dirty(page);
+ /*
+ * Track the pages being written.
+ */
+ HgfsInodePageWbAdd(inode, page);
}
- set_page_dirty(page);
+ HgfsDoExtendFile(inode, writeTo);
LOG(6, (KERN_WARNING "VMware hgfs: %s: return 0\n", __func__));
return 0;
@@ -1106,7 +1388,7 @@ HgfsCommitWrite(struct file *file, // IN: File to write
ASSERT(page);
ASSERT(file);
- offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+ offset = (loff_t)HGFS_PAGE_FILE_INDEX(page) << PAGE_CACHE_SHIFT;
writeTo = offset + pageTo;
copied = pageTo - pageFrom;
@@ -1164,7 +1446,7 @@ HgfsWriteEnd(struct file *file, // IN: File to write
mapping->host->i_ino, len, (long long) pos, copied));
if (copied < len) {
- zero_user_segment(page, pageFrom + copied, pageFrom + len);
+ HgfsZeroUserSegment(page, pageFrom + copied, pageFrom + len);
}
ret = HgfsDoWriteEnd(file, page, pageFrom, pageTo, writeTo, copied);
@@ -1174,6 +1456,779 @@ HgfsWriteEnd(struct file *file, // IN: File to write
compat_unlock_page(page);
page_cache_release(page);
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: return %d\n", __func__, ret));
return ret;
}
#endif
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbPageAlloc --
+ *
+ * Allocates a write-back page object.
+ *
+ * Results:
+ * The write-back page object
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline HgfsWbPage *
+HgfsWbPageAlloc(void)
+{
+ return kmalloc(sizeof (HgfsWbPage), GFP_KERNEL);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbPageAlloc --
+ *
+ * Frees a write-back page object.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+
+static inline void
+HgfsWbPageFree(HgfsWbPage *page) // IN: request of page data to write
+{
+ ASSERT(page);
+ kfree(page);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestFree --
+ *
+ * Frees the resources for a write-back page request.
+ * Calls the request destroy and then frees the object memory.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsWbRequestFree(struct kref *kref) // IN: ref field request of page data to write
+{
+ HgfsWbPage *req = container_of(kref, HgfsWbPage, wb_kref);
+
+ /* Release write back request page and free it. */
+ HgfsWbRequestDestroy(req);
+ HgfsWbPageFree(req);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestGet --
+ *
+ * Reference the write-back page request.
+ * Calls the request destroy and then frees the object memory.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+HgfsWbRequestGet(HgfsWbPage *req) // IN: request of page data to write
+{
+ kref_get(&req->wb_kref);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestPut --
+ *
+ * Remove a reference the write-back page request.
+ * Calls the request free to tear down the object memory if it was the
+ * final one.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Destroys the request if last one.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+HgfsWbRequestPut(HgfsWbPage *req) // IN: request of page data to write
+{
+ kref_put(&req->wb_kref, HgfsWbRequestFree);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestWaitUninterruptible --
+ *
+ * Sleep function while waiting for requests to complete.
+ *
+ * Results:
+ * Always zero.
+ *
+ * Side effects:
+* None
+ *
+ *----------------------------------------------------------------------
+ */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) && \
+ LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
+static int
+HgfsWbRequestWaitUninterruptible(void *word) // IN:unused
+{
+ io_schedule();
+ return 0;
+}
+#endif
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestWait --
+ *
+ * Wait for a write-back page request to complete.
+ * Interruptible by fatal signals only.
+ * The user is responsible for holding a count on the request.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+
+int
+HgfsWbRequestWait(HgfsWbPage *req) // IN: request of page data to write
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+ return wait_on_bit_io(&req->wb_flags,
+ PG_BUSY,
+ TASK_UNINTERRUPTIBLE);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
+ return wait_on_bit(&req->wb_flags,
+ PG_BUSY,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
+ HgfsWbRequestWaitUninterruptible,
+#endif
+ TASK_UNINTERRUPTIBLE);
+#else
+ wait_event(req->wb_queue,
+ !test_bit(PG_BUSY, &req->wb_flags));
+ return 0;
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestLock --
+ *
+ * Lock the write-back page request.
+ *
+ * Results:
+ * Non-zero if the lock was not already locked
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline int
+HgfsWbRequestLock(HgfsWbPage *req) // IN: request of page data to write
+{
+ return !test_and_set_bit(PG_BUSY, &req->wb_flags);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestUnlock --
+ *
+ * Unlock the write-back page request.
+ * Wakes up any waiting threads on the lock.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsWbRequestUnlock(HgfsWbPage *req) // IN: request of page data to write
+{
+ if (!test_bit(PG_BUSY,&req->wb_flags)) {
+ LOG(6, (KERN_WARNING "VMware Hgfs: %s: Invalid unlock attempted\n", __func__));
+ return;
+ }
+ HGFS_SM_MB_BEFORE();
+ clear_bit(PG_BUSY, &req->wb_flags);
+ HGFS_SM_MB_AFTER();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
+ wake_up_bit(&req->wb_flags, PG_BUSY);
+#else
+ wake_up(&req->wb_queue);
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestUnlockAndPut --
+ *
+ * Unlock the write-back page request and removes a reference.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsWbRequestUnlockAndPut(HgfsWbPage *req) // IN: request of page data to write
+{
+ HgfsWbRequestUnlock(req);
+ HgfsWbRequestPut(req);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestListAdd --
+ *
+ * Add the write-back page request into the list.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline void
+HgfsWbRequestListAdd(HgfsWbPage *req, // IN: request of page data to write
+ struct list_head *head) // IN: list of requests
+{
+ list_add_tail(&req->wb_list, head);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestListRemove --
+ *
+ * Remove the write-back page request from the list.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline void
+HgfsWbRequestListRemove(HgfsWbPage *req) // IN: request of page data to write
+{
+ if (!list_empty(&req->wb_list)) {
+ list_del_init(&req->wb_list);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestCreate --
+ *
+ * Create the write-back page request.
+ *
+ * Results:
+ * The new write-back page request.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+HgfsWbPage *
+HgfsWbRequestCreate(struct page *page) // IN: page of data to write
+{
+ HgfsWbPage *wbReq;
+ /* try to allocate the request struct */
+ wbReq = HgfsWbPageAlloc();
+ if (wbReq == NULL) {
+ wbReq = ERR_PTR(-ENOMEM);
+ goto exit;
+ }
+
+ /*
+ * Initialize the request struct. Initially, we assume a
+ * long write-back delay. This will be adjusted in
+ * update_nfs_request below if the region is not locked.
+ */
+ wbReq->wb_flags = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
+ init_waitqueue_head(&wbReq->wb_queue);
+#endif
+ INIT_LIST_HEAD(&wbReq->wb_list);
+ wbReq->wb_page = page;
+ wbReq->wb_index = HGFS_PAGE_FILE_INDEX(page);
+ page_cache_get(page);
+ kref_init(&wbReq->wb_kref);
+
+exit:
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: (%p, %p)\n",
+ __func__, wbReq, page));
+ return wbReq;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWbRequestDestroy --
+ *
+ * Destroys by freeing up all resources allocated to the request.
+ * Release page associated with a write-back request after it has completed.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsWbRequestDestroy(HgfsWbPage *req) // IN: write page request
+{
+ struct page *page = req->wb_page;
+
+ LOG(6, (KERN_WARNING"VMware hgfs: %s: (%p, %p)\n",
+ __func__, req, req->wb_page));
+
+ if (page != NULL) {
+ page_cache_release(page);
+ req->wb_page = NULL;
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInodeFindWbRequest --
+ *
+ * Finds if there is a write-back page request on this inode and returns it.
+ *
+ * Results:
+ * NULL or the write-back request for the page.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static HgfsWbPage *
+HgfsInodeFindWbRequest(struct inode *inode, // IN: inode of file to write to
+ struct page *page) // IN: page of data to write
+{
+ HgfsInodeInfo *iinfo;
+ HgfsWbPage *req = NULL;
+ HgfsWbPage *cur;
+
+ iinfo = INODE_GET_II_P(inode);
+
+ /* Linearly search the write back list for the correct req */
+ list_for_each_entry(cur, &iinfo->listWbPages, wb_list) {
+ if (cur->wb_page == page) {
+ req = cur;
+ break;
+ }
+ }
+
+ if (req != NULL) {
+ HgfsWbRequestGet(req);
+ }
+
+ return req;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInodeFindExistingWbRequest --
+ *
+ * Finds if there is a write-back page request on this inode and returns
+ * locked.
+ * If the request is busy (locked) then it drops the lock and waits for it
+ * be not locked and searches the list again.
+ *
+ * Results:
+ * NULL or the write-back request for the page.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static HgfsWbPage *
+HgfsInodeFindExistingWbRequest(struct inode *inode, // IN: inode of file to write to
+ struct page *page) // IN: page of data to write
+{
+ HgfsWbPage *req;
+ int error;
+
+ spin_lock(&inode->i_lock);
+
+ for (;;) {
+ req = HgfsInodeFindWbRequest(inode, page);
+ if (req == NULL) {
+ goto out_exit;
+ }
+
+ /*
+ * Try and lock the request if not already locked.
+ * If we find it is already locked, busy, then we drop
+ * the reference and wait to try again. Otherwise,
+ * once newly locked we break out and return to the caller.
+ */
+ if (HgfsWbRequestLock(req)) {
+ break;
+ }
+
+ /* The request was in use, so wait and then retry */
+ spin_unlock(&inode->i_lock);
+ error = HgfsWbRequestWait(req);
+ HgfsWbRequestPut(req);
+ if (error != 0) {
+ goto out_nolock;
+ }
+
+ spin_lock(&inode->i_lock);
+ }
+
+out_exit:
+ spin_unlock(&inode->i_lock);
+ return req;
+
+out_nolock:
+ return ERR_PTR(error);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInodeAddWbRequest --
+ *
+ * Add a write-back page request to an inode.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsInodeAddWbRequest(struct inode *inode, // IN: inode of file to write to
+ HgfsWbPage *req) // IN: page write request
+{
+ HgfsInodeInfo *iinfo = INODE_GET_II_P(inode);
+
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: (%p, %p, %lu)\n",
+ __func__, inode, req->wb_page, iinfo->numWbPages));
+
+ /* Lock the request! */
+ HgfsWbRequestLock(req);
+
+ HgfsWbRequestListAdd(req, &iinfo->listWbPages);
+ iinfo->numWbPages++;
+ HgfsWbRequestGet(req);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInodeRemoveWbRequest --
+ *
+ * Remove a write-back page request from an inode.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsInodeRemoveWbRequest(struct inode *inode, // IN: inode of file written to
+ HgfsWbPage *req) // IN: page write request
+{
+ HgfsInodeInfo *iinfo = INODE_GET_II_P(inode);
+
+ LOG(6, (KERN_CRIT "VMware hgfs: %s: (%p, %p, %lu)\n",
+ __func__, inode, req->wb_page, iinfo->numWbPages));
+
+ iinfo->numWbPages--;
+ HgfsWbRequestListRemove(req);
+ HgfsWbRequestPut(req);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInodePageWbAdd --
+ *
+ * Add a write-back page request to an inode.
+ * If the page is already exists in the list for this inode nothing is
+ * done, otherwise a new object is created for the page and added to the
+ * inode list.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsInodePageWbAdd(struct inode *inode, // IN: inode of file to write to
+ struct page *page) // IN: page of data to write
+{
+ HgfsWbPage *req;
+
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: (%p, %p)\n",
+ __func__, inode, page));
+
+ req = HgfsInodeFindExistingWbRequest(inode, page);
+ if (req != NULL) {
+ goto exit;
+ }
+
+ /*
+ * We didn't find an existing write back request for that page so
+ * we create one.
+ */
+ req = HgfsWbRequestCreate(page);
+ if (IS_ERR(req)) {
+ goto exit;
+ }
+
+ spin_lock(&inode->i_lock);
+ /*
+ * Add the new write request for the page into our inode list to track.
+ */
+ HgfsInodeAddWbRequest(inode, req);
+ spin_unlock(&inode->i_lock);
+
+exit:
+ if (!IS_ERR(req)) {
+ HgfsWbRequestUnlockAndPut(req);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInodePageWbRemove --
+ *
+ * Remove a write-back page request from an inode.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsInodePageWbRemove(struct inode *inode, // IN: inode of file written to
+ struct page *page) // IN: page of data written
+{
+ HgfsWbPage *req;
+
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: (%p, %p)\n",
+ __func__, inode, page));
+
+ req = HgfsInodeFindExistingWbRequest(inode, page);
+ if (req == NULL) {
+ goto exit;
+ }
+ spin_lock(&inode->i_lock);
+ /*
+ * Add the new write request for the page into our inode list to track.
+ */
+ HgfsInodeRemoveWbRequest(inode, req);
+ HgfsWbRequestUnlockAndPut(req);
+ spin_unlock(&inode->i_lock);
+
+exit:
+ return;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInodePageWbFind --
+ *
+ * Find a write-back page request from an inode.
+ *
+ * Results:
+ * TRUE if found an existing write for the page, FALSE otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+HgfsInodePageWbFind(struct inode *inode, // IN: inode of file written to
+ struct page *page) // IN: page of data written
+{
+ HgfsWbPage *req;
+ Bool found = TRUE;
+
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: (%p, %p)\n",
+ __func__, inode, page));
+
+ req = HgfsInodeFindExistingWbRequest(inode, page);
+ if (req == NULL) {
+ found = FALSE;
+ goto exit;
+ }
+ spin_lock(&inode->i_lock);
+ /*
+ * Remove the write request lock and reference we just grabbed.
+ */
+ HgfsWbRequestUnlockAndPut(req);
+ spin_unlock(&inode->i_lock);
+
+exit:
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: (%p, %p) return %d\n",
+ __func__, inode, page, found));
+ return found;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsCheckReadModifyWrite --
+ *
+ * Check if we can read the page from the server to get the valid data
+ * for a page that we are in process of partially modifying and then
+ * writing.
+ *
+ * We maybe required to read the page first if the file is open for
+ * reading in addition to writing, the page is not marked as uptodate,
+ * it is not dirty or waiting to be committed, indicating that it was
+ * previously allocated and then modified, that there were valid bytes
+ * of data in that range of the file, and that the new data won't completely
+ * replace the old data in that range of the file.
+ *
+ * Results:
+ * TRUE if we need to read valid data and can do so for the page,
+ * FALSE otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+HgfsCheckReadModifyWrite(struct file *file, // IN: File to be written
+ struct page *page, // IN: page of data written
+ unsigned int pageFrom, // IN: position
+ unsigned int pageTo) // IN: len
+{
+ unsigned int pageLength = HgfsGetPageLength(page);
+ struct inode *inode = page->mapping->host;
+ Bool readPage = FALSE;
+
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: (%p, %u, %u)\n",
+ __func__, page, pageFrom, pageTo));
+
+ if ((file->f_mode & FMODE_READ) && // opened for read?
+ !HgfsInodePageWbFind(inode, page) && // I/O request already ?
+ !PageUptodate(page) && // Up to date?
+ pageLength > 0 && // valid bytes of file?
+ (pageTo < pageLength || pageFrom != 0)) { // replace all valid bytes?
+ readPage = TRUE;
+ }
+
+ LOG(6, (KERN_WARNING "VMware hgfs: %s: (%p, %u, %u) return %d\n",
+ __func__, page, pageFrom, pageTo, readPage));
+ return readPage;
+}
diff --git a/open-vm-tools/modules/linux/vmhgfs/request.h b/open-vm-tools/modules/linux/vmhgfs/request.h
index 4303924b..7537ac51 100644
--- a/open-vm-tools/modules/linux/vmhgfs/request.h
+++ b/open-vm-tools/modules/linux/vmhgfs/request.h
@@ -36,8 +36,8 @@
#include "compat_spinlock.h"
#include "hgfs.h" /* For common HGFS definitions. */
-#include "hgfsTransport.h"
#include "vm_basic_types.h"
+#include "vm_basic_defs.h"
/* Macros for accessing the payload portion of the HGFS request packet. */
#define HGFS_REQ_PAYLOAD(hgfsReq) ((hgfsReq)->payload)
diff --git a/open-vm-tools/modules/linux/vmhgfs/transport.c b/open-vm-tools/modules/linux/vmhgfs/transport.c
index 760ae7bf..c7fdb04c 100644
--- a/open-vm-tools/modules/linux/vmhgfs/transport.c
+++ b/open-vm-tools/modules/linux/vmhgfs/transport.c
@@ -155,7 +155,7 @@ HgfsTransportSetupNewChannel(void)
HgfsTransportChannel *newChannel;
newChannel = HgfsGetBdChannel();
- LOG(10, ("CHANNEL: Bd channel\n"));
+ LOG(10, (KERN_DEBUG LGPFX "%s CHANNEL: Bd channel\n", __func__));
ASSERT(newChannel);
hgfsChannel = newChannel;
return HgfsTransportOpenChannel(newChannel);
@@ -242,7 +242,7 @@ HgfsTransportFlushPendingRequests(void)
list_for_each_entry(req, &hgfsRepPending, list) {
if (req->state == HGFS_REQ_STATE_SUBMITTED) {
- LOG(6, ("VMware hgfs: %s: injecting error reply to req id: %d\n",
+ LOG(6, (KERN_DEBUG LGPFX "%s: injecting error reply to req id: %d\n",
__func__, req->id));
HgfsFailReq(req, -EIO);
}
@@ -427,7 +427,7 @@ HgfsTransportSendRequest(HgfsReq *req) // IN: Request to send
if (likely(ret == 0))
break;
- LOG(4, (KERN_DEBUG "VMware hgfs: %s: send failed with error %d\n",
+ LOG(4, (KERN_DEBUG LGPFX "%s: send failed with error %d\n",
__func__, ret));
if (ret == -EINTR) {
@@ -527,7 +527,7 @@ HgfsTransportInit(void)
void
HgfsTransportMarkDead(void)
{
- LOG(8, ("VMware hgfs: %s entered.\n", __func__));
+ LOG(8, (KERN_DEBUG LGPFX "%s entered.\n", __func__));
compat_mutex_lock(&hgfsChannelLock);
@@ -559,7 +559,7 @@ HgfsTransportMarkDead(void)
void
HgfsTransportExit(void)
{
- LOG(8, ("VMware hgfs: %s entered.\n", __func__));
+ LOG(8, (KERN_DEBUG LGPFX "%s entered.\n", __func__));
compat_mutex_lock(&hgfsChannelLock);
ASSERT(hgfsChannel);
@@ -568,7 +568,7 @@ HgfsTransportExit(void)
compat_mutex_unlock(&hgfsChannelLock);
ASSERT(list_empty(&hgfsRepPending));
- LOG(8, ("VMware hgfs: %s exited.\n", __func__));
+ LOG(8, (KERN_DEBUG LGPFX "%s exited.\n", __func__));
}
diff --git a/open-vm-tools/modules/linux/vmhgfs/vmhgfs_version.h b/open-vm-tools/modules/linux/vmhgfs/vmhgfs_version.h
index c5f19dcc..a2953005 100644
--- a/open-vm-tools/modules/linux/vmhgfs/vmhgfs_version.h
+++ b/open-vm-tools/modules/linux/vmhgfs/vmhgfs_version.h
@@ -25,8 +25,8 @@
#ifndef _VMHGFS_VERSION_H_
#define _VMHGFS_VERSION_H_
-#define VMHGFS_DRIVER_VERSION 1.4.1.1
-#define VMHGFS_DRIVER_VERSION_COMMAS 1,4,1,1
-#define VMHGFS_DRIVER_VERSION_STRING "1.4.1.1"
+#define VMHGFS_DRIVER_VERSION 2.0.17.0
+#define VMHGFS_DRIVER_VERSION_COMMAS 2,0,17,0
+#define VMHGFS_DRIVER_VERSION_STRING "2.0.17.0"
#endif /* _VMHGFS_VERSION_H_ */
diff --git a/open-vm-tools/modules/linux/vsock/linux/af_vsock.c b/open-vm-tools/modules/linux/vsock/linux/af_vsock.c
index bde14970..c068a1a7 100644
--- a/open-vm-tools/modules/linux/vsock/linux/af_vsock.c
+++ b/open-vm-tools/modules/linux/vsock/linux/af_vsock.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007-2014 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -175,6 +175,7 @@ static void VSockVmciPeerAttachCB(VMCIId subId,
static void VSockVmciPeerDetachCB(VMCIId subId,
VMCI_EventData *ed, void *clientData);
static void VSockVmciRecvPktWork(compat_work_arg work);
+static void VSockVmciDelayedSockPut(compat_work_arg work);
static int VSockVmciRecvListen(struct sock *sk, VSockPacket *pkt);
static int VSockVmciRecvConnectingServer(struct sock *sk,
struct sock *pending, VSockPacket *pkt);
@@ -366,6 +367,11 @@ typedef struct VSockRecvPktInfo {
VSockPacket pkt;
} VSockRecvPktInfo;
+typedef struct VSockDelayedSockPut {
+ compat_work work;
+ struct sock *sk;
+} VSockDelayedSockPut;
+
static compat_define_mutex(registrationMutex);
static int devOpenCount = 0;
static int vsockVmciSocketCount = 0;
@@ -1028,6 +1034,7 @@ VSockVmciRecvStreamCB(void *data, // IN
VMCIId expectedSrcRid;
Bool bhProcessPkt;
int err;
+ VSockDelayedSockPut *delayedSockPut;
ASSERT(dg);
ASSERT(dg->payloadSize <= VMCI_MAX_DG_PAYLOAD_SIZE);
@@ -1055,6 +1062,15 @@ VSockVmciRecvStreamCB(void *data, // IN
return VMCI_ERROR_INVALID_ARGS;
}
+ /*
+ * We need to preallocate this since we otherwise may end up in a situation
+ * where we can't put the socket due to out of memory.
+ */
+ delayedSockPut = kmalloc(sizeof *delayedSockPut, GFP_ATOMIC);
+ if (!delayedSockPut) {
+ return VMCI_ERROR_NO_MEM;
+ }
+
pkt = (VSockPacket *)dg;
LOG_PACKET(pkt);
@@ -1170,7 +1186,12 @@ VSockVmciRecvStreamCB(void *data, // IN
out:
if (sk) {
- sock_put(sk);
+ delayedSockPut->sk = sk;
+ COMPAT_INIT_WORK(&delayedSockPut->work, VSockVmciDelayedSockPut,
+ delayedSockPut);
+ compat_schedule_work(&delayedSockPut->work);
+ } else {
+ kfree(delayedSockPut);
}
return err;
}
@@ -1488,6 +1509,35 @@ out:
/*
*----------------------------------------------------------------------------
*
+ * VSockVmciDelayedSocketPut --
+ *
+ * Drops a reference to the given socket.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Socket may be freed.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static void
+VSockVmciDelayedSockPut(compat_work_arg work) // IN
+{
+ VSockDelayedSockPut *delayedSockPut;
+
+ delayedSockPut = COMPAT_WORK_GET_DATA(work, VSockDelayedSockPut, work);
+ ASSERT(delayedSockPut);
+
+ sock_put(delayedSockPut->sk);
+ kfree(delayedSockPut);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
* VSockVmciRecvPktWork --
*
* Handles an incoming control packet for the provided socket. This is the
diff --git a/open-vm-tools/modules/linux/vsock/linux/notify.c b/open-vm-tools/modules/linux/vsock/linux/notify.c
index f6279560..5b1e134c 100644
--- a/open-vm-tools/modules/linux/vsock/linux/notify.c
+++ b/open-vm-tools/modules/linux/vsock/linux/notify.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2009-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/vsock/linux/notify.h b/open-vm-tools/modules/linux/vsock/linux/notify.h
index 17b06027..0da29b9e 100644
--- a/open-vm-tools/modules/linux/vsock/linux/notify.h
+++ b/open-vm-tools/modules/linux/vsock/linux/notify.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2009-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/vsock/linux/notifyQState.c b/open-vm-tools/modules/linux/vsock/linux/notifyQState.c
index f3816d4b..464454b3 100644
--- a/open-vm-tools/modules/linux/vsock/linux/notifyQState.c
+++ b/open-vm-tools/modules/linux/vsock/linux/notifyQState.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2009-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/vsock/linux/vsockCommon.h b/open-vm-tools/modules/linux/vsock/linux/vsockCommon.h
index f86f2148..0b326d4e 100644
--- a/open-vm-tools/modules/linux/vsock/linux/vsockCommon.h
+++ b/open-vm-tools/modules/linux/vsock/linux/vsockCommon.h
@@ -140,7 +140,7 @@
static INLINE void *
VSockVA64ToPtr(VA64 va64) // IN
{
-#ifdef VM_X86_64
+#ifdef VM_64BIT
ASSERT_ON_COMPILE(sizeof (void *) == 8);
#else
ASSERT_ON_COMPILE(sizeof (void *) == 4);
diff --git a/open-vm-tools/modules/linux/vsock/linux/vsockSocketWrapper.h b/open-vm-tools/modules/linux/vsock/linux/vsockSocketWrapper.h
index d7fcaf74..acfa9faf 100644
--- a/open-vm-tools/modules/linux/vsock/linux/vsockSocketWrapper.h
+++ b/open-vm-tools/modules/linux/vsock/linux/vsockSocketWrapper.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/linux/vsock/linux/vsock_version.h b/open-vm-tools/modules/linux/vsock/linux/vsock_version.h
index f46bf539..52502ca9 100644
--- a/open-vm-tools/modules/linux/vsock/linux/vsock_version.h
+++ b/open-vm-tools/modules/linux/vsock/linux/vsock_version.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2011-2014 VMware, Inc. All rights reserved.
+ * Copyright (C) 2011-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -25,8 +25,8 @@
#ifndef _VSOCK_VERSION_H_
#define _VSOCK_VERSION_H_
-#define VSOCK_DRIVER_VERSION 9.7.1.0
-#define VSOCK_DRIVER_VERSION_COMMAS 9,7,1,0
-#define VSOCK_DRIVER_VERSION_STRING "9.7.1.0"
+#define VSOCK_DRIVER_VERSION 9.8.1.0
+#define VSOCK_DRIVER_VERSION_COMMAS 9,8,1,0
+#define VSOCK_DRIVER_VERSION_STRING "9.8.1.0"
#endif /* _VSOCK_VERSION_H_ */
diff --git a/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c b/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c
index 3ea87736..9bf41630 100644
--- a/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c
+++ b/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ * Copyright (C) 2012,2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -284,9 +284,9 @@ Backdoor_MonitorLockPage(Balloon *b, // IN/OUT
&b->resetFlag);
/* update stats */
- STATS_INC(b->stats.lock);
+ STATS_INC(b->stats.lock[FALSE]);
if (status != BALLOON_SUCCESS) {
- STATS_INC(b->stats.lockFail);
+ STATS_INC(b->stats.lockFail[FALSE]);
}
return status;
@@ -328,9 +328,9 @@ Backdoor_MonitorUnlockPage(Balloon *b, // IN/OUT
&b->resetFlag);
/* update stats */
- STATS_INC(b->stats.unlock);
+ STATS_INC(b->stats.unlock[FALSE]);
if (status != BALLOON_SUCCESS) {
- STATS_INC(b->stats.unlockFail);
+ STATS_INC(b->stats.unlockFail[FALSE]);
}
return status;
@@ -353,18 +353,27 @@ Backdoor_MonitorUnlockPage(Balloon *b, // IN/OUT
*/
int
-Backdoor_MonitorLockPagesBatched(Balloon *b, // IN/OUT
- PPN64 ppn, // IN
- uint32 nPages, // IN
- uint32 *target) // OUT
+Backdoor_MonitorLockPagesBatched(Balloon *b, // IN/OUT
+ PPN64 ppn, // IN
+ uint32 nPages, // IN
+ int isLargePage, // IN
+ uint32 *target) // OUT
{
- int status = BackdoorCmd(BALLOON_BDOOR_CMD_BATCHED_LOCK,
- (size_t)ppn, nPages, target, &b->resetFlag);
+ int status;
+ uint16 cmd;
+
+ if (isLargePage) {
+ cmd = BALLOON_BDOOR_CMD_BATCHED_2M_LOCK;
+ } else {
+ cmd = BALLOON_BDOOR_CMD_BATCHED_LOCK;
+ }
+
+ status = BackdoorCmd(cmd, (size_t)ppn, nPages, target, &b->resetFlag);
/* update stats */
- STATS_INC(b->stats.lock);
+ STATS_INC(b->stats.lock[isLargePage]);
if (status != BALLOON_SUCCESS) {
- STATS_INC(b->stats.lockFail);
+ STATS_INC(b->stats.lockFail[isLargePage]);
}
return status;
@@ -387,18 +396,27 @@ Backdoor_MonitorLockPagesBatched(Balloon *b, // IN/OUT
*/
int
-Backdoor_MonitorUnlockPagesBatched(Balloon *b, // IN/OUT
- PPN64 ppn, // IN
- uint32 nPages, // IN
- uint32 *target) // OUT
+Backdoor_MonitorUnlockPagesBatched(Balloon *b, // IN/OUT
+ PPN64 ppn, // IN
+ uint32 nPages, // IN
+ int isLargePage, // IN
+ uint32 *target) // OUT
{
- int status = BackdoorCmd(BALLOON_BDOOR_CMD_BATCHED_UNLOCK,
- (size_t)ppn, nPages, target, &b->resetFlag);
+ int status;
+ uint16 cmd;
+
+ if (isLargePage) {
+ cmd = BALLOON_BDOOR_CMD_BATCHED_2M_UNLOCK;
+ } else {
+ cmd = BALLOON_BDOOR_CMD_BATCHED_UNLOCK;
+ }
+
+ status = BackdoorCmd(cmd, (size_t)ppn, nPages, target, &b->resetFlag);
/* update stats */
- STATS_INC(b->stats.unlock);
+ STATS_INC(b->stats.unlock[isLargePage]);
if (status != BALLOON_SUCCESS) {
- STATS_INC(b->stats.unlockFail);
+ STATS_INC(b->stats.unlockFail[isLargePage]);
}
return status;
diff --git a/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h b/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h
index 5e26ebe8..7256c71e 100644
--- a/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h
+++ b/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007,2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -75,8 +75,8 @@ int Backdoor_MonitorGetTarget(Balloon *b, uint32 *target);
int Backdoor_MonitorLockPage(Balloon *b, PPN64 ppn, uint32 *target);
int Backdoor_MonitorUnlockPage(Balloon *b, PPN64 ppn, uint32 *target);
int Backdoor_MonitorLockPagesBatched(Balloon *b, PPN64 ppn, uint32 nPages,
- uint32 *target);
+ int isLargePages, uint32 *target);
int Backdoor_MonitorUnlockPagesBatched(Balloon *b, PPN64 ppn, uint32 nPages,
- uint32 *target);
+ int isLargePages, uint32 *target);
#endif /* _BACKDOOR_BALLOON_H_ */
diff --git a/open-vm-tools/modules/shared/vmmemctl/balloonInt.h b/open-vm-tools/modules/shared/vmmemctl/balloonInt.h
index 5c472124..bada6ce4 100644
--- a/open-vm-tools/modules/shared/vmmemctl/balloonInt.h
+++ b/open-vm-tools/modules/shared/vmmemctl/balloonInt.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ * Copyright (C) 2012,2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -64,7 +64,10 @@
#define BALLOON_NAME "vmmemctl"
#define BALLOON_NAME_VERBOSE "VMware memory control driver"
-#if defined __linux__ || defined __FreeBSD__ || defined _WIN32
+#if defined __linux__ || (defined __APPLE__ && defined __LP64__)
+#define BALLOON_CAPABILITIES (BALLOON_BASIC_CMDS|BALLOON_BATCHED_CMDS|\
+ BALLOON_BATCHED_2M_CMDS)
+#elif defined __FreeBSD__ || defined _WIN32 || (defined __APPLE__ && !defined __LP64__)
#define BALLOON_CAPABILITIES (BALLOON_BASIC_CMDS|BALLOON_BATCHED_CMDS)
#else
#define BALLOON_CAPABILITIES BALLOON_BASIC_CMDS
diff --git a/open-vm-tools/modules/shared/vmmemctl/balloon_def.h b/open-vm-tools/modules/shared/vmmemctl/balloon_def.h
index 0ba139cf..5600114a 100644
--- a/open-vm-tools/modules/shared/vmmemctl/balloon_def.h
+++ b/open-vm-tools/modules/shared/vmmemctl/balloon_def.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2000-2012 VMware, Inc. All rights reserved.
+ * Copyright (C) 2000-2012,2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -96,6 +96,9 @@
* | GUEST_ID | Always available |
* | BATCHED_LOCK | BATCHED_CMDS |
* | BATCHED_UNLOCK | BATCHED_CMDS |
+ * | BATCHED_2M_LOCK | BATCHED_2M_CMDS |
+ * | BATCHED_2M_UNLOCK | BATCHED_2M_CMDS |
+ * | VMCI_DOORBELL_SET | SIGNALED_WAKEUP_CMD |
* +====================+======================+
*
* (*) The START command has been slightly modified when more than the
@@ -110,14 +113,17 @@
*/
/* backdoor command numbers */
-#define BALLOON_BDOOR_CMD_START (0)
-#define BALLOON_BDOOR_CMD_TARGET (1)
-#define BALLOON_BDOOR_CMD_LOCK (2)
-#define BALLOON_BDOOR_CMD_UNLOCK (3)
-#define BALLOON_BDOOR_CMD_GUEST_ID (4)
+#define BALLOON_BDOOR_CMD_START (0)
+#define BALLOON_BDOOR_CMD_TARGET (1)
+#define BALLOON_BDOOR_CMD_LOCK (2)
+#define BALLOON_BDOOR_CMD_UNLOCK (3)
+#define BALLOON_BDOOR_CMD_GUEST_ID (4)
/* The command 5 was shortly used between 1881144 and 1901153. */
-#define BALLOON_BDOOR_CMD_BATCHED_LOCK (6)
-#define BALLOON_BDOOR_CMD_BATCHED_UNLOCK (7)
+#define BALLOON_BDOOR_CMD_BATCHED_LOCK (6)
+#define BALLOON_BDOOR_CMD_BATCHED_UNLOCK (7)
+#define BALLOON_BDOOR_CMD_BATCHED_2M_LOCK (8)
+#define BALLOON_BDOOR_CMD_BATCHED_2M_UNLOCK (9)
+#define BALLOON_BDOOR_CMD_VMCI_DOORBELL_SET (10)
/* balloon capabilities */
typedef enum {
@@ -130,7 +136,9 @@ typedef enum {
* LOCK and UNLOCK.
*/
BALLOON_BASIC_CMDS = (1 << 1),
- BALLOON_BATCHED_CMDS = (1 << 2)
+ BALLOON_BATCHED_CMDS = (1 << 2),
+ BALLOON_BATCHED_2M_CMDS = (1 << 3),
+ BALLOON_SIGNALED_WAKEUP_CMD = (1 << 4),
} BalloonCapabilities;
/* use config value for max balloon size */
@@ -169,7 +177,7 @@ typedef enum {
/*
* BatchPage.
*/
-#define BALLOON_BATCH_MAX_PAGES (PAGE_SIZE / sizeof(PA64))
+#define BALLOON_BATCH_MAX_ENTRIES (PAGE_SIZE / sizeof(PA64))
/*
* We are using the fact that for 4k pages, the 12LSB are set to 0, so
@@ -182,10 +190,6 @@ typedef enum {
* +=============+==========+========+
* 64 PAGE_SHIFT 6 0
*
- * For now, only 4k pages are supported by the monitor, but by using
- * reserved bit we can in the future add some flags that will indicate
- * whether the page is a 2M page or a 1G page.
- *
* The reserved field should be set to 0.
*
*/
@@ -195,7 +199,7 @@ typedef enum {
#define BALLOON_BATCH_PAGE_MASK (~MASK64(PAGE_SHIFT))
typedef struct BalloonBatchPage {
- PA64 pages[BALLOON_BATCH_MAX_PAGES];
+ PA64 entries[BALLOON_BATCH_MAX_ENTRIES];
} BalloonBatchPage;
@@ -218,8 +222,8 @@ static INLINE PA64
Balloon_BatchGetPA(BalloonBatchPage *batchPage, // IN
uint16 idx) // IN
{
- ASSERT(idx < BALLOON_BATCH_MAX_PAGES);
- return batchPage->pages[idx] & BALLOON_BATCH_PAGE_MASK;
+ ASSERT(idx < BALLOON_BATCH_MAX_ENTRIES);
+ return batchPage->entries[idx] & BALLOON_BATCH_PAGE_MASK;
}
@@ -242,8 +246,8 @@ static INLINE uint8
Balloon_BatchGetStatus(BalloonBatchPage *batchPage, // IN
uint16 idx) // IN
{
- ASSERT(idx < BALLOON_BATCH_MAX_PAGES);
- return (uint8)(batchPage->pages[idx] & BALLOON_BATCH_STATUS_MASK);
+ ASSERT(idx < BALLOON_BATCH_MAX_ENTRIES);
+ return (uint8)(batchPage->entries[idx] & BALLOON_BATCH_STATUS_MASK);
}
@@ -267,9 +271,9 @@ Balloon_BatchSetPA(BalloonBatchPage *batchPage, // IN
uint16 idx, // IN
PA64 pa) // IN
{
- ASSERT(idx < BALLOON_BATCH_MAX_PAGES);
+ ASSERT(idx < BALLOON_BATCH_MAX_ENTRIES);
ASSERT((pa & ~BALLOON_BATCH_PAGE_MASK) == 0);
- batchPage->pages[idx] = pa;
+ batchPage->entries[idx] = pa;
}
@@ -294,9 +298,9 @@ Balloon_BatchSetStatus(BalloonBatchPage *batchPage, // IN
int error) // IN
{
PA64 pa = Balloon_BatchGetPA(batchPage, idx);
- ASSERT(idx < BALLOON_BATCH_MAX_PAGES);
+ ASSERT(idx < BALLOON_BATCH_MAX_ENTRIES);
ASSERT(error <= BALLOON_ERROR_BUSY && error >= BALLOON_FAILURE);
- batchPage->pages[idx] = pa | (PPN64)error;
+ batchPage->entries[idx] = pa | (PPN64)error;
}
MY_ASSERTS(BALLOON_BATCH_SIZE,
diff --git a/open-vm-tools/modules/shared/vmmemctl/dbllnklst.h b/open-vm-tools/modules/shared/vmmemctl/dbllnklst.h
index 95745826..2037dcdb 100644
--- a/open-vm-tools/modules/shared/vmmemctl/dbllnklst.h
+++ b/open-vm-tools/modules/shared/vmmemctl/dbllnklst.h
@@ -115,7 +115,7 @@ typedef struct DblLnkLst_Links {
*/
static INLINE void
-DblLnkLst_Init(DblLnkLst_Links *l) // IN
+DblLnkLst_Init(DblLnkLst_Links *l) // OUT
{
l->prev = l->next = l;
}
@@ -141,8 +141,8 @@ DblLnkLst_Init(DblLnkLst_Links *l) // IN
*/
static INLINE void
-DblLnkLst_Link(DblLnkLst_Links *l1, // IN
- DblLnkLst_Links *l2) // IN
+DblLnkLst_Link(DblLnkLst_Links *l1, // IN/OUT
+ DblLnkLst_Links *l2) // IN/OUT
{
DblLnkLst_Links *tmp;
@@ -175,8 +175,8 @@ DblLnkLst_Link(DblLnkLst_Links *l1, // IN
*/
static INLINE void
-DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN
- DblLnkLst_Links *l2) // IN
+DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN/OUT
+ DblLnkLst_Links *l2) // IN/OUT
{
DblLnkLst_Links *tmp;
@@ -203,7 +203,7 @@ DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN
*/
static INLINE void
-DblLnkLst_Unlink1(DblLnkLst_Links *l) // IN
+DblLnkLst_Unlink1(DblLnkLst_Links *l) // IN/OUT
{
DblLnkLst_Unlink(l, l->next);
}
@@ -253,8 +253,8 @@ DblLnkLst_IsLinked(DblLnkLst_Links const *l) // IN
*/
static INLINE void
-DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN
- DblLnkLst_Links *l) // IN
+DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN/OUT
+ DblLnkLst_Links *l) // IN/OUT
{
DblLnkLst_Link(head->next, l);
}
@@ -277,8 +277,8 @@ DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN
*/
static INLINE void
-DblLnkLst_LinkLast(DblLnkLst_Links *head, // IN
- DblLnkLst_Links *l) // IN
+DblLnkLst_LinkLast(DblLnkLst_Links *head, // IN/OUT
+ DblLnkLst_Links *l) // IN/OUT
{
DblLnkLst_Link(head, l);
}
diff --git a/open-vm-tools/modules/shared/vmmemctl/kernelStubsSal.h b/open-vm-tools/modules/shared/vmmemctl/kernelStubsSal.h
new file mode 100644
index 00000000..d88b0497
--- /dev/null
+++ b/open-vm-tools/modules/shared/vmmemctl/kernelStubsSal.h
@@ -0,0 +1,173 @@
+/*********************************************************
+ * Copyright (C) 2014 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*********************************************************
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*********************************************************
+ * The contents of this file are subject to the terms of the Common
+ * Development and Distribution License (the "License") version 1.0
+ * and no later version. You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ * http://www.opensource.org/licenses/cddl1.php
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ *********************************************************/
+
+/*
+ * kernelStubsSal.h
+ *
+ * Contains definitions source annotation language definitions for kernel drivers.
+ * This solves two issues:
+ * 1. Microsoft changed their annotation language from SAL 1.0 (original one
+ * widely distributed by the Windows team) to their more final SAL 2.0
+ * langauge (championed by the VS team). We target multiple versions of
+ * Driver Kits, so we have to map 2.0 to 1.0.
+ * 2. We want these annotations to do nothing during non-Win32 compiles.
+ *
+ * A longer term goal is to rationalize this into Bora.
+ */
+#ifndef __KERNELSTUBSSAL_H__
+#define __KERNELSTUBSSAL_H__
+
+#if defined(_WIN32)
+# include <DriverSpecs.h>
+# if !defined(_SAL_VERSION)
+# define _SAL_VERSION 10
+# endif
+#endif
+
+#if !defined(_SAL_VERSION)
+#define _In_
+#define _In_z_
+#define _In_opt_
+#define _In_opt_z_
+#define _Out_
+#define _Out_opt_
+#define _Out_z_cap_(e)
+#define _Inout_
+#define _Inout_z_cap_(e)
+#define _Post_z_count_(e)
+#define _Ret_writes_z_(e)
+#define _Ret_writes_maybenull_z_(e)
+#define _Ret_maybenull_z_
+#define _Success_(expr)
+#define _Check_return_
+#define _Must_inspect_result_
+#define _Group_(annos)
+#define _When_(expr, annos)
+#define _Printf_format_string_
+#define _Use_decl_annotations_
+#elif defined(_SAL_VERSION) && _SAL_VERSION == 10
+// Microsoft didn't create a header mapping SAL 2.0 to 1.0. We do that here.
+#define _In_ __in
+#define _In_z_ __in_z
+#define _In_opt_ __in_opt
+#define _In_opt_z_ __in_z_opt
+#define _Out_ __out
+#define _Out_opt_ __out_opt
+#define _Out_z_cap_(expr) __out_ecount_z(expr)
+#define _Inout_ __inout
+#define _Inout_z_cap_(expr) __inout_ecount_z(expr)
+#define _Post_z_count_(expr)
+#define _Ret_writes_z_(expr) __out_ecount_z(expr)
+#define _Ret_writes_maybenull_z_(expr) __out_ecount_z_opt(expr)
+#define _Ret_maybenull_z_ __out_z
+#define _Check_return_ __checkReturn
+#define _Must_inspect_result_ __checkReturn
+#define _Success_(annos) __success(annos)
+#define _Printf_format_string_ __format_string
+#define _Use_decl_annotations_
+
+// DriverSpecs.h was pretty much empty until the DDK that defined
+// NTDDK_WIN6SP1 appeared.
+#if defined(NTDDI_WIN6SP1)
+#define _Group_(annos) __$drv_group(annos)
+#define _When_(expr, annos) __drv_when(expr, annos)
+#define _IRQL_requires_max_(irql) __drv_maxIRQL(irql)
+#else
+#define _Group_(annos)
+#define _When_(expr, annos)
+#define _IRQL_requires_max_(irql)
+#define __drv_allocatesMem(kind)
+#define __drv_freesMem(kind)
+#endif
+
+#else
+// Sal 2.0 path - everything is already defined.
+#endif // _SAL_VERSION
+
+// Now define our own annotations
+#if !defined(_SAL_VERSION)
+#define _When_windrv_(annos)
+#define _Ret_allocates_malloc_mem_opt_bytecap_(_Size)
+#define _Ret_allocates_malloc_mem_opt_bytecount_(_Size)
+#define _Ret_allocates_malloc_mem_opt_bytecap_post_bytecount_(_Cap,_Count)
+#define _Ret_allocates_malloc_mem_opt_z_bytecount_(_Size)
+#define _Ret_allocates_malloc_mem_opt_z_
+#define _In_frees_malloc_mem_opt_
+#elif defined(_SAL_VERSION) && _SAL_VERSION == 10
+#define _When_windrv_(annos) annos
+#define _Ret_allocates_malloc_mem_opt_bytecap_(_Cap) __drv_allocatesMem("Memory") __checkReturn __post __byte_writableTo(_Cap) __exceptthat __maybenull
+#define _Ret_allocates_malloc_mem_opt_bytecount_(_Count) __drv_allocatesMem("Memory") __checkReturn __post __byte_readableTo(_Count) __exceptthat __maybenull
+#define _Ret_allocates_malloc_mem_opt_bytecap_post_bytecount_(_Cap,_Count) __drv_allocatesMem("Memory") __checkReturn __post __byte_writableTo(_Cap) __byte_readableTo(_Count) __exceptthat __maybenull
+#define _Ret_allocates_malloc_mem_opt_z_bytecount_(_Count) __drv_allocatesMem("Memory") __checkReturn __post __byte_readableTo(_Count) __valid __nullterminated __exceptthat __maybenull
+#define _Ret_allocates_malloc_mem_opt_z_ __drv_allocatesMem("Memory") __checkReturn __post __valid __nullterminated __exceptthat __maybenull
+#define _In_frees_malloc_mem_opt_ __drv_freesMem("Memory") __in_opt __post __notvalid
+#else
+#define _When_windrv_(annos) annos
+#define _Ret_allocates_malloc_mem_opt_bytecap_(_Cap) __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_bytecap_(_Cap)
+#define _Ret_allocates_malloc_mem_opt_bytecount_(_Count) __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_bytecount_(_Count)
+#define _Ret_allocates_malloc_mem_opt_bytecap_post_bytecount_(_Cap,_Count) __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_bytecap_(_Cap) _Ret_opt_bytecount_(_Count)
+#define _Ret_allocates_malloc_mem_opt_z_bytecount_(_Count) __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_z_bytecount_(_Count)
+#define _Ret_allocates_malloc_mem_opt_z_ __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_z_
+#define _In_frees_malloc_mem_opt_ __drv_freesMem("Memory") _Pre_maybenull_ _Post_invalid_
+#endif // _SAL_VERSION
+
+// Best we can do for reallocate with simple annotations: assume old size was fully initialized.
+#define _Ret_reallocates_malloc_mem_opt_newbytecap_oldbytecap_(_NewSize, _OldSize) _Ret_allocates_malloc_mem_opt_bytecap_post_bytecount_(_NewSize, _OldSize <= _NewSize ? _OldSize : _NewSize)
+#define _Ret_reallocates_malloc_mem_opt_newbytecap_(_NewSize) _Ret_allocates_malloc_mem_opt_z_bytecount_(_NewSize)
+#define _In_reallocates_malloc_mem_opt_oldptr_ _In_frees_malloc_mem_opt_
+
+#endif // __KERNELSTUBSSAL_H__
diff --git a/open-vm-tools/modules/shared/vmmemctl/os.h b/open-vm-tools/modules/shared/vmmemctl/os.h
index e02bc67f..a1e9c0a9 100644
--- a/open-vm-tools/modules/shared/vmmemctl/os.h
+++ b/open-vm-tools/modules/shared/vmmemctl/os.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2000 VMware, Inc. All rights reserved.
+ * Copyright (C) 2000,2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -80,6 +80,10 @@ typedef uintptr_t Mapping;
#define PAGE_HANDLE_INVALID 0
#define MAPPING_INVALID 0
+#define OS_SMALL_PAGE_ORDER (0) // 4 KB small pages
+#define OS_LARGE_PAGE_ORDER (9) // 2 MB large pages
+#define OS_LARGE_2_SMALL_PAGES (1 << OS_LARGE_PAGE_ORDER)
+
/*
* Operations
*/
@@ -95,8 +99,8 @@ extern void OS_Yield(void);
extern unsigned long OS_ReservedPageGetLimit(void);
extern PA64 OS_ReservedPageGetPA(PageHandle handle);
extern PageHandle OS_ReservedPageGetHandle(PA64 pa);
-extern PageHandle OS_ReservedPageAlloc(int canSleep);
-extern void OS_ReservedPageFree(PageHandle handle);
+extern PageHandle OS_ReservedPageAlloc(int canSleep, int isLargePage);
+extern void OS_ReservedPageFree(PageHandle handle, int isLargePage);
extern Mapping OS_MapPageHandle(PageHandle handle);
extern void *OS_Mapping2Addr(Mapping mapping);
diff --git a/open-vm-tools/modules/shared/vmmemctl/vmballoon.c b/open-vm-tools/modules/shared/vmmemctl/vmballoon.c
index 9df059d0..00864c62 100644
--- a/open-vm-tools/modules/shared/vmmemctl/vmballoon.c
+++ b/open-vm-tools/modules/shared/vmmemctl/vmballoon.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2000 VMware, Inc. All rights reserved.
+ * Copyright (C) 2000,2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -102,16 +102,20 @@ extern "C" {
/*
* Balloon operations
*/
-static void BalloonPageFree(Balloon *b);
+static void BalloonPageFree(Balloon *b, int isLargePage);
static void BalloonAdjustSize(Balloon *b, uint32 target);
static void BalloonReset(Balloon *b);
static void BalloonAddPage(Balloon *b, uint16 idx, PageHandle page);
static void BalloonAddPageBatched(Balloon *b, uint16 idx, PageHandle page);
-static int BalloonLock(Balloon *b, uint16 nPages, uint32 *target);
-static int BalloonLockBatched(Balloon *b, uint16 nPages, uint32 *target);
-static int BalloonUnlock(Balloon *b, uint16 nPages, uint32 *target);
-static int BalloonUnlockBatched(Balloon *b, uint16 nPages, uint32 *target);
+static int BalloonLock(Balloon *b, uint16 nPages, int isLargePage,
+ uint32 *target);
+static int BalloonLockBatched(Balloon *b, uint16 nPages, int isLargePages,
+ uint32 *target);
+static int BalloonUnlock(Balloon *b, uint16 nPages, int isLargePages,
+ uint32 *target);
+static int BalloonUnlockBatched(Balloon *b, uint16 nPages, int IsLargePages,
+ uint32 *target);
/*
* Globals
@@ -237,9 +241,9 @@ BalloonChunk_Destroy(BalloonChunk *chunk) // IN
/*
*----------------------------------------------------------------------
*
- * Balloon_Deallocate --
+ * Balloon_DeallocateChunkList --
*
- * Frees all allocated pages.
+ * Frees all allocated pages of a size
*
* Results:
* None.
@@ -251,18 +255,47 @@ BalloonChunk_Destroy(BalloonChunk *chunk) // IN
*/
static void
-Balloon_Deallocate(Balloon *b) // IN/OUT
+Balloon_DeallocateChunkList(Balloon *b, // IN/OUT
+ int isLargePages) // IN
{
unsigned int cnt = 0;
+ BalloonChunkList *chunkList;
+
+ chunkList = &b->pages[isLargePages];
/* free all pages, skipping monitor unlock */
- while (b->nChunks > 0) {
- BalloonPageFree(b);
+ while (chunkList->nChunks > 0) {
+ BalloonPageFree(b, isLargePages);
if (++cnt >= b->rateFree) {
cnt = 0;
OS_Yield();
}
}
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Balloon_Deallocate --
+ *
+ * Frees all allocated pages.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+Balloon_Deallocate(Balloon *b) // IN/OUT
+{
+ /* free all pages, skipping monitor unlock */
+ Balloon_DeallocateChunkList(b, FALSE);
+ Balloon_DeallocateChunkList(b, TRUE);
/* Release the batch page */
if (b->batchPageMapping != MAPPING_INVALID) {
@@ -272,7 +305,7 @@ Balloon_Deallocate(Balloon *b) // IN/OUT
}
if (b->pageHandle != PAGE_HANDLE_INVALID) {
- OS_ReservedPageFree(b->pageHandle);
+ OS_ReservedPageFree(b->pageHandle, FALSE);
b->pageHandle = PAGE_HANDLE_INVALID;
}
}
@@ -296,16 +329,16 @@ Balloon_Deallocate(Balloon *b) // IN/OUT
static int
BalloonInitBatching(Balloon *b) // OUT
{
- b->batchMaxPages = BALLOON_BATCH_MAX_PAGES;
+ b->batchMaxEntries = BALLOON_BATCH_MAX_ENTRIES;
- b->pageHandle = OS_ReservedPageAlloc(BALLOON_PAGE_ALLOC_NOSLEEP);
+ b->pageHandle = OS_ReservedPageAlloc(FALSE, FALSE);
if (b->pageHandle == PAGE_HANDLE_INVALID) {
return BALLOON_PAGE_ALLOC_FAILURE;
}
b->batchPageMapping = OS_MapPageHandle(b->pageHandle);
if (b->batchPageMapping == MAPPING_INVALID) {
- OS_ReservedPageFree(b->pageHandle);
+ OS_ReservedPageFree(b->pageHandle, FALSE);
b->pageHandle = PAGE_HANDLE_INVALID;
return BALLOON_PAGE_ALLOC_FAILURE;
}
@@ -363,7 +396,7 @@ BalloonReset(Balloon *b) // OUT
b->balloonOps = &balloonOpsBatched;
} else if ((b->hypervisorCapabilities & BALLOON_BASIC_CMDS) != 0) {
b->balloonOps = &balloonOps;
- b->batchMaxPages = 1;
+ b->batchMaxEntries = 1;
}
/* clear flag */
@@ -442,26 +475,30 @@ Balloon_QueryAndExecute(void)
*/
static int
-BalloonErrorPageStore(Balloon *b, // IN/OUT
- PageHandle page) // IN
+BalloonErrorPageStore(Balloon *b, // IN/OUT
+ PageHandle page, // IN
+ int isLargePage) // IN
{
+ BalloonErrorPages *errors = &b->errors[isLargePage];
+
/* fail if list already full */
- if (b->errors.pageCount >= BALLOON_ERROR_PAGES) {
+ if (errors->nEntries >= BALLOON_ERROR_PAGES) {
return BALLOON_FAILURE;
}
/* add page to list */
- b->errors.page[b->errors.pageCount++] = page;
- STATS_INC(b->stats.primErrorPageAlloc);
+ errors->entries[errors->nEntries++] = page;
+ STATS_INC(b->stats.primErrorPageAlloc[isLargePage]);
return BALLOON_SUCCESS;
}
+
/*
*----------------------------------------------------------------------
*
- * BalloonErrorPagesFree --
+ * BalloonErrorPagesFreeInt --
*
- * Deallocates all pages on the list of non-balloonable pages
+ * Deallocates all pages of a size on the list of non-balloonable pages
* associated with "b".
*
* Results:
@@ -474,17 +511,44 @@ BalloonErrorPageStore(Balloon *b, // IN/OUT
*/
static void
-BalloonErrorPagesFree(Balloon *b) // IN/OUT
+BalloonErrorPagesFreeInt(Balloon *b, // IN/OUT
+ int isLargePage) // IN
{
unsigned int i;
+ BalloonErrorPages *errors = &b->errors[isLargePage];
/* free all non-balloonable "error" pages */
- for (i = 0; i < b->errors.pageCount; i++) {
- OS_ReservedPageFree(b->errors.page[i]);
- b->errors.page[i] = PAGE_HANDLE_INVALID;
- STATS_INC(b->stats.primErrorPageFree);
+ for (i = 0; i < errors->nEntries; i++) {
+ OS_ReservedPageFree(errors->entries[i], isLargePage);
+ errors->entries[i] = PAGE_HANDLE_INVALID;
+ STATS_INC(b->stats.primErrorPageFree[isLargePage]);
}
- b->errors.pageCount = 0;
+ errors->nEntries = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonErrorPagesFree --
+ *
+ * Deallocates all pages on the list of non-balloonable pages
+ * associated with "b".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BalloonErrorPagesFree(Balloon *b) // IN/OUT
+{
+ BalloonErrorPagesFreeInt(b, FALSE);
+ BalloonErrorPagesFreeInt(b, TRUE);
}
@@ -506,14 +570,16 @@ BalloonErrorPagesFree(Balloon *b) // IN/OUT
*/
static BalloonChunk *
-BalloonGetChunk(Balloon *b) // IN/OUT
+BalloonGetChunk(Balloon *b, // IN/OUT
+ int isLargePage) // IN
{
BalloonChunk *chunk;
+ BalloonChunkList *chunkList = &b->pages[isLargePage];
/* Get first chunk from the list */
- if (DblLnkLst_IsLinked(&b->chunks)) {
- chunk = DblLnkLst_Container(b->chunks.next, BalloonChunk, node);
- if (chunk->pageCount < BALLOON_CHUNK_PAGES) {
+ if (DblLnkLst_IsLinked(&chunkList->chunks)) {
+ chunk = DblLnkLst_Container(chunkList->chunks.next, BalloonChunk, node);
+ if (chunk->nEntries < BALLOON_CHUNK_ENTRIES) {
/* This chunk has free slots, use it */
return chunk;
}
@@ -522,10 +588,10 @@ BalloonGetChunk(Balloon *b) // IN/OUT
/* create new chunk */
chunk = BalloonChunk_Create();
if (chunk != NULL) {
- DblLnkLst_LinkFirst(&b->chunks, &chunk->node);
+ DblLnkLst_LinkFirst(&chunkList->chunks, &chunk->node);
/* update stats */
- b->nChunks++;
+ chunkList->nChunks++;
}
return chunk;
@@ -550,15 +616,19 @@ BalloonGetChunk(Balloon *b) // IN/OUT
*/
static BalloonChunk *
-BalloonGetChunkOrFallback(Balloon *b) // IN/OUT
+BalloonGetChunkOrFallback(Balloon *b, // IN/OUT
+ int isLargePage) // IN
{
- BalloonChunk *chunk = BalloonGetChunk(b);
+ BalloonChunk *chunk = BalloonGetChunk(b, isLargePage);
if (chunk == NULL) {
+ BalloonChunkList *chunkList = &b->pages[isLargePage];
+
ASSERT(b->fallbackChunk != NULL);
chunk = b->fallbackChunk;
b->fallbackChunk = NULL;
- DblLnkLst_LinkFirst(&b->chunks, &chunk->node);
- b->nChunks++;
+
+ DblLnkLst_LinkFirst(&chunkList->chunks, &chunk->node);
+ chunkList->nChunks++;
}
return chunk;
@@ -584,7 +654,7 @@ static void
BalloonPageStore(BalloonChunk *chunk, // IN/OUT
PageHandle page) // IN
{
- chunk->page[chunk->pageCount++] = page;
+ chunk->entries[chunk->nEntries++] = page;
}
/*
@@ -605,15 +675,16 @@ BalloonPageStore(BalloonChunk *chunk, // IN/OUT
static void
BalloonChunkDestroyEmpty(Balloon *b, // IN/OUT
- BalloonChunk *chunk) // IN/OUT
+ BalloonChunk *chunk, // IN/OUT
+ int isLargePage) // IN
{
- if (chunk->pageCount == 0) {
+ if (chunk->nEntries == 0) {
/* destroy empty chunk */
DblLnkLst_Unlink1(&chunk->node);
BalloonChunk_Destroy(chunk);
/* update stats */
- b->nChunks--;
+ b->pages[isLargePage].nChunks--;
}
}
@@ -635,26 +706,29 @@ BalloonChunkDestroyEmpty(Balloon *b, // IN/OUT
*/
static void
-BalloonPageFree(Balloon *b) // IN/OUT
+BalloonPageFree(Balloon *b, // IN/OUT
+ int isLargePage) // IN
{
+ BalloonChunkList *chunkList = &b->pages[isLargePage];
BalloonChunk *chunk;
PageHandle page;
- ASSERT(DblLnkLst_IsLinked(&b->chunks));
- chunk = DblLnkLst_Container(b->chunks.next, BalloonChunk, node);
+ ASSERT(DblLnkLst_IsLinked(&chunkList->chunks));
+ chunk = DblLnkLst_Container(chunkList->chunks.next, BalloonChunk, node);
/* deallocate last page */
- page = chunk->page[--chunk->pageCount];
+ page = chunk->entries[--chunk->nEntries];
/* deallocate page */
- OS_ReservedPageFree(page);
- STATS_INC(b->stats.primFree);
+ OS_ReservedPageFree(page, isLargePage);
+
+ STATS_INC(b->stats.primFree[isLargePage]);
/* update balloon size */
b->nPages--;
/* reclaim chunk, if empty */
- BalloonChunkDestroyEmpty(b, chunk);
+ BalloonChunkDestroyEmpty(b, chunk, isLargePage);
}
/*
@@ -677,14 +751,30 @@ static void
BalloonInflate(Balloon *b, // IN/OUT
uint32 target) // IN
{
- uint32 nPages;
+ uint32 nEntries;
unsigned int rate;
unsigned int allocations = 0;
int status = BALLOON_SUCCESS;
- BalloonPageAllocType allocType = BALLOON_PAGE_ALLOC_NOSLEEP;
+ BalloonPageAllocType allocType;
+ Bool isLargePages;
+ unsigned numPagesPerEntry;
+
+ if ((b->hypervisorCapabilities & BALLOON_BATCHED_2M_CMDS) != 0) {
+ allocType = BALLOON_PAGE_ALLOC_LPAGE;
+ isLargePages = TRUE;
+ numPagesPerEntry = OS_LARGE_2_SMALL_PAGES;
+ } else {
+ allocType = BALLOON_PAGE_ALLOC_NOSLEEP;
+ isLargePages = FALSE;
+ numPagesPerEntry = 1;
+ }
/*
- * First try NOSLEEP page allocations to inflate balloon.
+ * We try allocating in the following order:
+ *
+ * First we try to allocate large pages without sleeping. If the
+ * memory becomes too fragmented to allocate whole large pages at
+ * once, switch to small pages - still without sleeping.
*
* If we do not throttle nosleep allocations, we can drain all
* free pages in the guest quickly (if the balloon target is high).
@@ -705,49 +795,77 @@ BalloonInflate(Balloon *b, // IN/OUT
rate = b->slowPageAllocationCycles ?
b->rateAlloc : BALLOON_NOSLEEP_ALLOC_MAX;
- nPages = 0;
- while (b->nPages < target && nPages < target - b->nPages) {
+ nEntries = 0;
+ while (b->nPages < target &&
+ nEntries * numPagesPerEntry < target - b->nPages) {
PageHandle handle;
STATS_INC(b->stats.primAlloc[allocType]);
- handle = OS_ReservedPageAlloc(allocType);
+
+ handle = OS_ReservedPageAlloc(allocType == BALLOON_PAGE_ALLOC_CANSLEEP,
+ isLargePages);
+
if (handle == PAGE_HANDLE_INVALID) {
STATS_INC(b->stats.primAllocFail[allocType]);
status = BALLOON_PAGE_ALLOC_FAILURE;
- if (allocType == BALLOON_PAGE_ALLOC_CANSLEEP) {
+
+ if (allocType == BALLOON_PAGE_ALLOC_LPAGE) {
+ /*
+ * LPAGE allocation failed. This does mean that the guest is under
+ * pressure, it just means that the memory is fragmented enough that
+ * we cannot allocate any more large pages.
+ *
+ * Lock partial set of large pages now as we continue with
+ * allocating small pages and we cannot have a lock call with
+ * different entry sizes.
+ */
+ if (nEntries > 0) {
+ status = b->balloonOps->lock(b, nEntries, TRUE, &target);
+ nEntries = 0;
+ }
+
+ /* Continue with small pages */
+ isLargePages = FALSE;
+ numPagesPerEntry = 1;
+ allocType = BALLOON_PAGE_ALLOC_NOSLEEP;
+ } else if (allocType == BALLOON_PAGE_ALLOC_NOSLEEP) {
+ /*
+ * NOSLEEP page allocation failed, so the guest is under memory
+ * pressure. Let us slow down page allocations for next few cycles
+ * so that the guest gets out of memory pressure. Also, if we
+ * already allocated b->rateAlloc pages, let's pause, otherwise
+ * switch to sleeping allocations.
+ */
+ b->slowPageAllocationCycles = SLOW_PAGE_ALLOCATION_CYCLES;
+
+ /* Lower rate for sleeping allocations. */
+ rate = b->rateAlloc;
+ allocType = BALLOON_PAGE_ALLOC_CANSLEEP;
+ } else {
+ ASSERT(allocType == BALLOON_PAGE_ALLOC_CANSLEEP);
/*
* CANSLEEP page allocation failed, so guest is under severe
* memory pressure. Quickly decrease allocation rate.
*/
b->rateAlloc = MAX(b->rateAlloc / 2, BALLOON_RATE_ALLOC_MIN);
+
+ /* Stop allocating any more memory */
break;
}
- /*
- * NOSLEEP page allocation failed, so the guest is under memory
- * pressure. Let us slow down page allocations for next few cycles
- * so that the guest gets out of memory pressure. Also, if we
- * already allocated b->rateAlloc pages, let's pause, otherwise
- * switch to sleeping allocations.
- */
- b->slowPageAllocationCycles = SLOW_PAGE_ALLOCATION_CYCLES;
-
if (allocations >= b->rateAlloc) {
break;
}
- allocType = BALLOON_PAGE_ALLOC_CANSLEEP;
- /* Lower rate for sleeping allocations. */
- rate = b->rateAlloc;
continue;
}
allocations++;
- b->balloonOps->addPage(b, nPages++, handle);
- if (nPages == b->batchMaxPages) {
- status = b->balloonOps->lock(b, nPages, &target);
- nPages = 0;
+ b->balloonOps->addPage(b, nEntries++, handle);
+ if (nEntries == b->batchMaxEntries) {
+ status = b->balloonOps->lock(b, nEntries, isLargePages, &target);
+ nEntries = 0;
if (status != BALLOON_SUCCESS) {
break;
@@ -764,8 +882,8 @@ BalloonInflate(Balloon *b, // IN/OUT
}
}
- if (nPages > 0) {
- b->balloonOps->lock(b, nPages, NULL);
+ if (nEntries > 0) {
+ b->balloonOps->lock(b, nEntries, isLargePages, NULL);
}
/*
@@ -802,12 +920,13 @@ BalloonInflate(Balloon *b, // IN/OUT
*/
static int
BalloonLockBatched(Balloon *b, // IN/OUT
- uint16 nPages, // IN
+ uint16 nEntries, // IN
+ int isLargePages, // IN
uint32 *target) // OUT
{
int status;
uint32 i;
- uint32 nLockedPages;
+ uint32 nLockedEntries;
PageHandle handle;
PPN64 batchPagePPN;
BalloonChunk *chunk = NULL;
@@ -818,28 +937,28 @@ BalloonLockBatched(Balloon *b, // IN/OUT
* Make sure that we will always have an available chunk before doing
* the LOCK_BATCHED call.
*/
- ASSERT(b->batchMaxPages < BALLOON_CHUNK_PAGES);
+ ASSERT(b->batchMaxEntries < BALLOON_CHUNK_ENTRIES);
b->fallbackChunk = BalloonChunk_Create();
if (b->fallbackChunk == NULL) {
status = BALLOON_PAGE_ALLOC_FAILURE;
} else {
- status = Backdoor_MonitorLockPagesBatched(b, batchPagePPN, nPages,
- target);
+ status = Backdoor_MonitorLockPagesBatched(b, batchPagePPN, nEntries,
+ isLargePages, target);
}
if (status != BALLOON_SUCCESS) {
- for (i = 0; i < nPages; i++) {
+ for (i = 0; i < nEntries; i++) {
PA64 pa = Balloon_BatchGetPA(b->batchPage, i);
handle = OS_ReservedPageGetHandle(pa);
- OS_ReservedPageFree(handle);
+ OS_ReservedPageFree(handle, isLargePages);
}
goto out;
}
- nLockedPages = 0;
- for (i = 0; i < nPages; i++) {
+ nLockedEntries = 0;
+ for (i = 0; i < nEntries; i++) {
PA64 pa;
int error;
@@ -850,13 +969,14 @@ BalloonLockBatched(Balloon *b, // IN/OUT
switch (error) {
case BALLOON_ERROR_PPN_PINNED:
case BALLOON_ERROR_PPN_INVALID:
- if (BalloonErrorPageStore(b, handle) == BALLOON_SUCCESS) {
+ if (BalloonErrorPageStore(b, handle, isLargePages)
+ == BALLOON_SUCCESS) {
break;
}
// Fallthrough.
case BALLOON_ERROR_RESET:
case BALLOON_ERROR_PPN_NOTNEEDED:
- OS_ReservedPageFree(handle);
+ OS_ReservedPageFree(handle, isLargePages);
break;
default:
/*
@@ -871,17 +991,21 @@ BalloonLockBatched(Balloon *b, // IN/OUT
}
if (chunk == NULL) {
- chunk = BalloonGetChunkOrFallback(b);
+ chunk = BalloonGetChunkOrFallback(b, isLargePages);
}
BalloonPageStore(chunk, handle);
- if (chunk->pageCount == BALLOON_CHUNK_PAGES) {
+ if (chunk->nEntries == BALLOON_CHUNK_ENTRIES) {
chunk = NULL;
}
- nLockedPages++;
+ nLockedEntries++;
}
- b->nPages += nLockedPages;
+ if (isLargePages) {
+ b->nPages += nLockedEntries * OS_LARGE_2_SMALL_PAGES;
+ } else {
+ b->nPages += nLockedEntries;
+ }
out:
if (b->fallbackChunk != NULL) {
@@ -910,49 +1034,55 @@ out:
*----------------------------------------------------------------------
*/
static int
-BalloonUnlockBatched(Balloon *b, // IN/OUT
- uint16 nPages, // IN
- uint32 *target) // OUT
+BalloonUnlockBatched(Balloon *b, // IN/OUT
+ uint16 nEntries, // IN
+ int isLargePages, // IN
+ uint32 *target) // OUT
{
uint32 i;
int status = BALLOON_SUCCESS;
- uint32 nUnlockedPages;
+ uint32 nUnlockedEntries;
PPN64 batchPagePPN;
BalloonChunk *chunk = NULL;
batchPagePPN = PA_2_PPN(OS_ReservedPageGetPA(b->pageHandle));
- status = Backdoor_MonitorUnlockPagesBatched(b, batchPagePPN, nPages, target);
+ status = Backdoor_MonitorUnlockPagesBatched(b, batchPagePPN, nEntries,
+ isLargePages, target);
if (status != BALLOON_SUCCESS) {
- for (i = 0; i < nPages; i++) {
+ for (i = 0; i < nEntries; i++) {
PA64 pa = Balloon_BatchGetPA(b->batchPage, i);
PageHandle handle = OS_ReservedPageGetHandle(pa);
- chunk = BalloonGetChunkOrFallback(b);
+ chunk = BalloonGetChunkOrFallback(b, isLargePages);
BalloonPageStore(chunk, handle);
}
goto out;
}
- nUnlockedPages = 0;
- for (i = 0; i < nPages; i++) {
+ nUnlockedEntries = 0;
+ for (i = 0; i < nEntries; i++) {
int status = Balloon_BatchGetStatus(b->batchPage, i);
PA64 pa = Balloon_BatchGetPA(b->batchPage, i);
PageHandle handle = OS_ReservedPageGetHandle(pa);
if (status != BALLOON_SUCCESS) {
- chunk = BalloonGetChunkOrFallback(b);
+ chunk = BalloonGetChunkOrFallback(b, isLargePages);
BalloonPageStore(chunk, handle);
continue;
}
- OS_ReservedPageFree(handle);
- STATS_INC(b->stats.primFree);
+ OS_ReservedPageFree(handle, isLargePages);
+ STATS_INC(b->stats.primFree[isLargePages]);
- nUnlockedPages++;
+ nUnlockedEntries++;
}
- b->nPages -= nUnlockedPages;
+ if (isLargePages) {
+ b->nPages -= nUnlockedEntries * OS_LARGE_2_SMALL_PAGES;
+ } else {
+ b->nPages -= nUnlockedEntries;
+ }
out:
if (b->fallbackChunk != NULL) {
@@ -1008,16 +1138,19 @@ BalloonAddPageBatched(Balloon *b, // IN
static int
BalloonLock(Balloon *b, // IN/OUT
uint16 nPages, // IN
+ int isLargePage, // IN
uint32 *target) // OUT
{
PPN pagePPN;
BalloonChunk *chunk;
int status;
+ ASSERT(!isLargePage);
+
/* Get the chunk to store allocated page. */
- chunk = BalloonGetChunk(b);
+ chunk = BalloonGetChunk(b, FALSE);
if (chunk == NULL) {
- OS_ReservedPageFree(b->pageHandle);
+ OS_ReservedPageFree(b->pageHandle, FALSE);
status = BALLOON_PAGE_ALLOC_FAILURE;
goto out;
}
@@ -1029,18 +1162,18 @@ BalloonLock(Balloon *b, // IN/OUT
int old_status = status;
/* We need to release the chunk if it was just allocated */
- BalloonChunkDestroyEmpty(b, chunk);
+ BalloonChunkDestroyEmpty(b, chunk, isLargePage);
if (status == BALLOON_ERROR_RESET ||
status == BALLOON_ERROR_PPN_NOTNEEDED) {
- OS_ReservedPageFree(b->pageHandle);
+ OS_ReservedPageFree(b->pageHandle, FALSE);
goto out;
}
/* place on list of non-balloonable pages, retry allocation */
- status = BalloonErrorPageStore(b, b->pageHandle);
+ status = BalloonErrorPageStore(b, b->pageHandle, FALSE);
if (status != BALLOON_SUCCESS) {
- OS_ReservedPageFree(b->pageHandle);
+ OS_ReservedPageFree(b->pageHandle, FALSE);
goto out;
}
@@ -1078,21 +1211,24 @@ out:
*/
static int
-BalloonUnlock(Balloon *b, // IN/OUT
- uint16 nPages, // IN
- uint32 *target) // OUT
+BalloonUnlock(Balloon *b, // IN/OUT
+ uint16 nPages, // IN
+ int isLargePage, // IN
+ uint32 *target) // OUT
{
PPN pagePPN = PA_2_PPN(OS_ReservedPageGetPA(b->pageHandle));
int status = Backdoor_MonitorUnlockPage(b, pagePPN, target);
+ ASSERT(!isLargePage);
+
if (status != BALLOON_SUCCESS) {
- BalloonChunk *chunk = BalloonGetChunkOrFallback(b);
+ BalloonChunk *chunk = BalloonGetChunkOrFallback(b, FALSE);
BalloonPageStore(chunk, b->pageHandle);
goto out;
}
- OS_ReservedPageFree(b->pageHandle);
- STATS_INC(b->stats.primFree);
+ OS_ReservedPageFree(b->pageHandle, FALSE);
+ STATS_INC(b->stats.primFree[FALSE]);
/* update balloon size */
b->nPages--;
@@ -1135,9 +1271,9 @@ BalloonAddPage(Balloon *b, // IN/OUT
/*
*----------------------------------------------------------------------
*
- * BalloonDeflate --
+ * BalloonDeflateInt --
*
- * Frees physical pages to deflate balloon.
+ * Frees physical pages of a given size to deflate balloon.
*
* Results:
* None.
@@ -1149,15 +1285,22 @@ BalloonAddPage(Balloon *b, // IN/OUT
*/
static void
-BalloonDeflate(Balloon *b, // IN/OUT
- uint32 target) // IN
+BalloonDeflateInt(Balloon *b, // IN/OUT
+ uint32 target, // IN
+ int isLargePages) // IN
{
int status = BALLOON_SUCCESS;
uint32 nPages, deallocations = 0;
BalloonChunk *chunk = NULL;
+ BalloonChunkList *chunkList = &b->pages[isLargePages];
+
+ if (chunkList->nChunks == 0) {
+ return;
+ }
nPages = 0;
- while (b->nPages > target && nPages < b->nPages - target) {
+ while (chunkList->nChunks > 0 && b->nPages > target
+ && nPages < b->nPages - target) {
PageHandle lockedHandle;
if (chunk == NULL) {
@@ -1166,26 +1309,27 @@ BalloonDeflate(Balloon *b, // IN/OUT
* deviation between the guest balloon size, and tracked
* pages...
*/
- ASSERT(DblLnkLst_IsLinked(&b->chunks));
- chunk = DblLnkLst_Container(b->chunks.next, BalloonChunk, node);
+ ASSERT(DblLnkLst_IsLinked(&chunkList->chunks));
+ chunk = DblLnkLst_Container(chunkList->chunks.next, BalloonChunk,
+ node);
}
- lockedHandle = chunk->page[--chunk->pageCount];
- if (!chunk->pageCount) {
+ lockedHandle = chunk->entries[--chunk->nEntries];
+ if (!chunk->nEntries) {
DblLnkLst_Unlink1(&chunk->node);
/*
* Do not free the chunk, we may need it if the UNLOCK cmd fails
*/
b->fallbackChunk = chunk;
- b->nChunks--;
+ chunkList->nChunks--;
chunk = NULL;
}
deallocations++;
b->balloonOps->addPage(b, nPages++, lockedHandle);
- if (nPages == b->batchMaxPages) {
- status = b->balloonOps->unlock(b, nPages, &target);
+ if (nPages == b->batchMaxEntries) {
+ status = b->balloonOps->unlock(b, nPages, isLargePages, &target);
nPages = 0;
if (status != BALLOON_SUCCESS) {
@@ -1200,7 +1344,7 @@ BalloonDeflate(Balloon *b, // IN/OUT
}
if (nPages) {
- b->balloonOps->unlock(b, nPages, NULL);
+ b->balloonOps->unlock(b, nPages, isLargePages, NULL);
}
if (BALLOON_RATE_ADAPT) {
@@ -1219,6 +1363,32 @@ BalloonDeflate(Balloon *b, // IN/OUT
/*
*----------------------------------------------------------------------
*
+ * BalloonDeflate --
+ *
+ * Frees physical pages to deflate balloon.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BalloonDeflate(Balloon *b, // IN/OUT
+ uint32 target) // IN
+{
+ /* Prefer to unlock small pages over unlocking large pages */
+ BalloonDeflateInt(b, target, FALSE);
+ BalloonDeflateInt(b, target, TRUE);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* BalloonAdjustSize --
*
* Attempts to allocate or deallocate physical pages in order
@@ -1237,9 +1407,15 @@ static void
BalloonAdjustSize(Balloon *b, // IN/OUT
uint32 target) // IN
{
+ /*
+ * When we only deal with large pages it can happen that we overshoot our
+ * target by OS_LARGE_2_SMALL_PAGES - 1 pages. To prevent a constant balloon,
+ * unballoon loop, allow the target to be OS_LARGE_2_SMALL_PAGES - 1 pages
+ * lower than the actual ballooned amount before we do something.
+ */
if (b->nPages < target) {
BalloonInflate(b, target);
- } else if (b->nPages > target) {
+ } else if (target == 0 || b->nPages > target + OS_LARGE_2_SMALL_PAGES - 1) {
BalloonDeflate(b, target);
}
}
@@ -1265,7 +1441,8 @@ Balloon_Init(BalloonGuest guestType) // IN
{
Balloon *b = &globalBalloon;
- DblLnkLst_Init(&b->chunks);
+ DblLnkLst_Init(&b->pages[TRUE].chunks);
+ DblLnkLst_Init(&b->pages[FALSE].chunks);
b->guestType = guestType;
diff --git a/open-vm-tools/modules/shared/vmmemctl/vmballoon.h b/open-vm-tools/modules/shared/vmmemctl/vmballoon.h
index b8193b0a..42c76014 100644
--- a/open-vm-tools/modules/shared/vmmemctl/vmballoon.h
+++ b/open-vm-tools/modules/shared/vmmemctl/vmballoon.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2000-2012 VMware, Inc. All rights reserved.
+ * Copyright (C) 2000-2012,2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
@@ -71,11 +71,13 @@
* Page allocation flags
*/
typedef enum BalloonPageAllocType {
- BALLOON_PAGE_ALLOC_NOSLEEP = 0,
- BALLOON_PAGE_ALLOC_CANSLEEP = 1,
+ BALLOON_PAGE_ALLOC_LPAGE = 0,
+ BALLOON_PAGE_ALLOC_NOSLEEP = 1,
+ BALLOON_PAGE_ALLOC_CANSLEEP = 2,
BALLOON_PAGE_ALLOC_TYPES_NR, // total number of alloc types
} BalloonPageAllocType;
+
/*
* Types
*/
@@ -96,15 +98,15 @@ typedef struct {
/* primitives */
uint32 primAlloc[BALLOON_PAGE_ALLOC_TYPES_NR];
uint32 primAllocFail[BALLOON_PAGE_ALLOC_TYPES_NR];
- uint32 primFree;
- uint32 primErrorPageAlloc;
- uint32 primErrorPageFree;
+ uint32 primFree[2];
+ uint32 primErrorPageAlloc[2];
+ uint32 primErrorPageFree[2];
/* monitor operations */
- uint32 lock;
- uint32 lockFail;
- uint32 unlock;
- uint32 unlockFail;
+ uint32 lock[2];
+ uint32 lockFail[2];
+ uint32 unlock[2];
+ uint32 unlockFail[2];
uint32 target;
uint32 targetFail;
uint32 start;
@@ -116,32 +118,38 @@ typedef struct {
#define BALLOON_ERROR_PAGES 16
typedef struct {
- PageHandle page[BALLOON_ERROR_PAGES];
- uint32 pageCount;
+ PageHandle entries[BALLOON_ERROR_PAGES];
+ uint32 nEntries;
} BalloonErrorPages;
-#define BALLOON_CHUNK_PAGES 1000
+#define BALLOON_CHUNK_ENTRIES 1000
typedef struct BalloonChunk {
- PageHandle page[BALLOON_CHUNK_PAGES];
- uint32 pageCount;
+ PageHandle entries[BALLOON_CHUNK_ENTRIES];
+ uint32 nEntries;
DblLnkLst_Links node;
} BalloonChunk;
struct BalloonOps;
typedef struct {
- /* sets of reserved physical pages */
DblLnkLst_Links chunks;
int nChunks;
+} BalloonChunkList;
+
+typedef struct {
+ /* sets of reserved physical pages */
+ BalloonChunkList pages[2];
/* transient list of non-balloonable pages */
- BalloonErrorPages errors;
+ BalloonErrorPages errors[2];
BalloonGuest guestType;
- /* balloon size */
+ /* balloon size (in small pages) */
int nPages;
+
+ /* target balloon size (in small pages) */
int nPagesTarget;
/* reset flag */
@@ -167,15 +175,15 @@ typedef struct {
PageHandle pageHandle;
Mapping batchPageMapping;
BalloonBatchPage *batchPage;
- uint16 batchMaxPages;
+ uint16 batchMaxEntries;
BalloonChunk *fallbackChunk;
} Balloon;
typedef struct BalloonOps {
- void (*addPage)(Balloon *b, uint16 idx, PageHandle page);
- int (*lock)(Balloon *b, uint16 nPages, uint32 *target);
- int (*unlock)(Balloon *b, uint16 nPages, uint32 *target);
+ void (*addPage)(Balloon *b, uint16 idx, PageHandle entries);
+ int (*lock)(Balloon *b, uint16 nPages, int isLargePages, uint32 *target);
+ int (*unlock)(Balloon *b, uint16 nPages, int isLargePages, uint32 *target);
} BalloonOps;
/*
diff --git a/open-vm-tools/modules/shared/vmxnet/eth_public.h b/open-vm-tools/modules/shared/vmxnet/eth_public.h
index 6a75f245..767ea14b 100644
--- a/open-vm-tools/modules/shared/vmxnet/eth_public.h
+++ b/open-vm-tools/modules/shared/vmxnet/eth_public.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2005 VMware, Inc. All rights reserved.
+ * Copyright (C) 2005-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/shared/vmxnet/net.h b/open-vm-tools/modules/shared/vmxnet/net.h
index e31fd071..88950a4a 100644
--- a/open-vm-tools/modules/shared/vmxnet/net.h
+++ b/open-vm-tools/modules/shared/vmxnet/net.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ * Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -96,6 +96,7 @@ typedef struct Net_AdapterCount {
uint8 vlance;
uint8 vmxnet2;
uint8 vmxnet3;
+ uint8 vrdma;
uint8 e1000;
uint8 e1000e;
} Net_AdapterCount;
@@ -187,6 +188,7 @@ Net_GetNumAdapters(Net_AdapterCount *counts)
counts->vlance = 0;
counts->vmxnet2 = 0;
counts->vmxnet3 = 0;
+ counts->vrdma = 0;
counts->e1000 = 0;
counts->e1000e = 0;
@@ -199,6 +201,8 @@ Net_GetNumAdapters(Net_AdapterCount *counts)
adapterStr = Config_GetString("vlance", "ethernet%d.virtualDev", i);
if (Str_Strcasecmp(adapterStr, "vmxnet3") == 0) {
counts->vmxnet3++;
+ } else if (Str_Strcasecmp(adapterStr, "vrdma") == 0) {
+ counts->vrdma++;
} else if (Str_Strcasecmp(adapterStr, "vlance") == 0) {
counts->vlance++;
} else if (Str_Strcasecmp(adapterStr, "vmxnet") == 0) {
@@ -210,7 +214,7 @@ Net_GetNumAdapters(Net_AdapterCount *counts)
} else {
LOG_ONCE(("%s: unknown adapter: %s\n", __FUNCTION__, adapterStr));
}
- free(adapterStr);
+ free(adapterStr);
}
}
diff --git a/open-vm-tools/modules/shared/vmxnet/upt1_defs.h b/open-vm-tools/modules/shared/vmxnet/upt1_defs.h
index ac546445..5bb3daa8 100644
--- a/open-vm-tools/modules/shared/vmxnet/upt1_defs.h
+++ b/open-vm-tools/modules/shared/vmxnet/upt1_defs.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/shared/vmxnet/vmnet_def.h b/open-vm-tools/modules/shared/vmxnet/vmnet_def.h
index 73252067..999c1bcb 100644
--- a/open-vm-tools/modules/shared/vmxnet/vmnet_def.h
+++ b/open-vm-tools/modules/shared/vmxnet/vmnet_def.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2004-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2004-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -49,7 +49,7 @@
#include "includeCheck.h"
#define VMNET_NAME_BUFFER_LEN 128 /* Increased for i18n. */
-#define VMNET_COAL_STRING_LEN 16
+#define VMNET_COAL_STRING_LEN 128
/*
diff --git a/open-vm-tools/modules/shared/vmxnet/vmxnet2_def.h b/open-vm-tools/modules/shared/vmxnet/vmxnet2_def.h
index d2bb293a..84387b74 100644
--- a/open-vm-tools/modules/shared/vmxnet/vmxnet2_def.h
+++ b/open-vm-tools/modules/shared/vmxnet/vmxnet2_def.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2004 VMware, Inc. All rights reserved.
+ * Copyright (C) 2004-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -173,28 +173,24 @@ typedef struct Vmxnet2_TxRingEntry {
* functions below to be used.
*/
typedef struct Vmxnet2_RxRingInfo {
-#ifdef VMX86_VMX
- PA basePA; /* starting PA of the ring */
-#else
+#ifndef VMX86_VMX
Vmxnet2_RxRingEntry *base; /* starting addr of the ring */
#endif
uint32 nicNext; /* next entry to use in the ring */
uint32 ringLength; /* # of entries in the ring */
- PA startPA; /* PA of the starting addr of the ring */
+ PA startPA; /* starting addr of the ring */
#ifdef VMX86_DEBUG
const char *name;
#endif
} Vmxnet2_RxRingInfo;
typedef struct Vmxnet2_TxRingInfo {
-#ifdef VMX86_VMX
- PA basePA; /* starting PA of the ring */
-#else
+#ifndef VMX86_VMX
Vmxnet2_TxRingEntry *base; /* starting addr of the ring */
#endif
uint32 nicNext; /* next entry to use in the ring */
uint32 ringLength; /* # of entries in the ring */
- PA startPA; /* PA of the starting addr of the ring */
+ PA startPA; /* starting addr of the ring */
#ifdef VMX86_DEBUG
const char *name;
#endif
@@ -327,13 +323,16 @@ typedef struct Vmxnet2_DriverData {
Vmxnet2_DriverStats stats;
} Vmxnet2_DriverData;
+#ifdef VMX86_SERVER
/*
* Shared between VMM and Vmkernel part of vmxnet2 to optimize action posting
* VMM writes 1 (don't post) or 0 (okay to post) and vmk reads this.
*/
typedef struct VmxnetVMKShared {
- uint32 dontPostActions;
+ uint32 dontPostActions;
+ PciHandle pciHandle;
} VmxnetVMKShared;
+#endif
#if defined VMKERNEL
diff --git a/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h b/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h
index b79ecdb4..dfc4657d 100644
--- a/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h
+++ b/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -354,7 +354,32 @@ struct Vmxnet3_RxCompDescExt {
uint8 segCnt; /* Number of aggregated packets */
uint8 dupAckCnt; /* Number of duplicate Acks */
__le16 tsDelta; /* TCP timestamp difference */
- __le32 dword2[2];
+ __le32 dword2;
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint32 gen:1; /* generation bit */
+ uint32 type:7; /* completion type */
+ uint32 fcs:1; /* Frame CRC correct */
+ uint32 frg:1; /* IP Fragment */
+ uint32 v4:1; /* IPv4 */
+ uint32 v6:1; /* IPv6 */
+ uint32 ipc:1; /* IP Checksum Correct */
+ uint32 tcp:1; /* TCP packet */
+ uint32 udp:1; /* UDP packet */
+ uint32 tuc:1; /* TCP/UDP Checksum Correct */
+ uint32 mss:16;
+#else
+ uint32 mss:16;
+ uint32 tuc:1; /* TCP/UDP Checksum Correct */
+ uint32 udp:1; /* UDP packet */
+ uint32 tcp:1; /* TCP packet */
+ uint32 ipc:1; /* IP Checksum Correct */
+ uint32 v6:1; /* IPv6 */
+ uint32 v4:1; /* IPv4 */
+ uint32 frg:1; /* IP Fragment */
+ uint32 fcs:1; /* Frame CRC correct */
+ uint32 type:7; /* completion type */
+ uint32 gen:1; /* generation bit */
+#endif /* __BIG_ENDIAN_BITFIELD */
}
#include "vmware_pack_end.h"
Vmxnet3_RxCompDescExt;
diff --git a/open-vm-tools/modules/shared/vmxnet/vmxnet_def.h b/open-vm-tools/modules/shared/vmxnet/vmxnet_def.h
index 703466c9..e94faf98 100644
--- a/open-vm-tools/modules/shared/vmxnet/vmxnet_def.h
+++ b/open-vm-tools/modules/shared/vmxnet/vmxnet_def.h
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 1999 VMware, Inc. All rights reserved.
+ * Copyright (C) 1999-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/open-vm-tools/modules/solaris/vmhgfs/filesystem.c b/open-vm-tools/modules/solaris/vmhgfs/filesystem.c
index 187be2c9..0240013e 100644
--- a/open-vm-tools/modules/solaris/vmhgfs/filesystem.c
+++ b/open-vm-tools/modules/solaris/vmhgfs/filesystem.c
@@ -293,6 +293,13 @@ HgfsMount(struct vfs *vfsp, // IN: Filesystem to mount
goto out;
}
+ if (mountData->size != sizeof *mountData) {
+ DEBUG(VM_DEBUG_FAIL, "HgfsMount: received invalid size value: %x\n",
+ mountData->magic);
+ ret = EINVAL;
+ goto out;
+ }
+
/* We support only one instance of hgfs, at least for now */
if (HgfsGetSuperInfo()) {
DEBUG(VM_DEBUG_FAIL, "HgfsMount: HGFS is already mounted somewhere\n");
diff --git a/open-vm-tools/modules/solaris/vmhgfs/filesystem.h b/open-vm-tools/modules/solaris/vmhgfs/filesystem.h
index 709fc218..5c05c4bc 100644
--- a/open-vm-tools/modules/solaris/vmhgfs/filesystem.h
+++ b/open-vm-tools/modules/solaris/vmhgfs/filesystem.h
@@ -55,17 +55,28 @@
/*
* Macros
+ *
+ * XXX - Must place these into a common header file that can be
+ * used here and by the Linux client and OS X clients (user and kernel)
+ * components.
*/
#define HGFS_MAGIC (0xbacbacbc)
#define HGFS_FSTYPE HGFS_FS_NAME
/*
* Struct passed from mount program to kernel (fs module)
+ *
+ * ******************* IMPORTANT ****************************
+ * XXX - This must be kept compatible with the HgfsMountInfo
+ * structure which is defined in hgfsDevLinux.h
+ * ******************* IMPORTANT ****************************
*/
typedef struct HgfsMountData {
uint32_t magic;
+ uint32_t size;
uint32_t version;
uint32_t fd;
+ uint32_t flags;
} HgfsMountData;
diff --git a/open-vm-tools/modules/solaris/vmmemctl/os.c b/open-vm-tools/modules/solaris/vmmemctl/os.c
index 93b76226..52b219b0 100644
--- a/open-vm-tools/modules/solaris/vmmemctl/os.c
+++ b/open-vm-tools/modules/solaris/vmmemctl/os.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2005 VMware, Inc. All rights reserved.
+ * Copyright (C) 2005,2014 VMware, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
@@ -392,7 +392,8 @@ OS_UnmapPage(Mapping mapping) // IN
*/
PageHandle
-OS_ReservedPageAlloc(int canSleep) // IN
+OS_ReservedPageAlloc(int canSleep, // IN
+ int isLargePage) // IN
{
os_state *state = &global_state;
page_t *pp;
@@ -403,6 +404,8 @@ OS_ReservedPageAlloc(int canSleep) // IN
vnode_t *vp = &state->vnode;
uint_t flags;
+ ASSERT(!isLargePage);
+
/*
* Reserve space for the page.
*/
@@ -471,7 +474,8 @@ OS_ReservedPageAlloc(int canSleep) // IN
*/
void
-OS_ReservedPageFree(PageHandle handle) // IN: A valid page handle
+OS_ReservedPageFree(PageHandle handle, // IN: A valid page handle
+ int isLargePage) // IN
{
os_state *state = &global_state;
os_page *page = (os_page *)handle;
@@ -479,6 +483,8 @@ OS_ReservedPageFree(PageHandle handle) // IN: A valid page handle
u_offset_t off = page->offset;
id_space_t *idp = state->id_space;
+ ASSERT(!isLargePage);
+
page_free(pp, 1);
page_unresv(1);
id_free(idp, offtoid(off));
diff --git a/open-vm-tools/modules/solaris/vmmemctl/vmballoon_kstats.c b/open-vm-tools/modules/solaris/vmmemctl/vmballoon_kstats.c
index 1c6063a8..671c6e84 100644
--- a/open-vm-tools/modules/solaris/vmmemctl/vmballoon_kstats.c
+++ b/open-vm-tools/modules/solaris/vmmemctl/vmballoon_kstats.c
@@ -103,19 +103,19 @@ BalloonKstatUpdate(kstat_t *ksp, int rw)
bkp->startFail.value.ui32 = stats->startFail;
bkp->guestType.value.ui32 = stats->guestType;
bkp->guestTypeFail.value.ui32 = stats->guestTypeFail;
- bkp->lock.value.ui32 = stats->lock;
- bkp->lockFail.value.ui32 = stats->lockFail;
- bkp->unlock.value.ui32 = stats->unlock;
- bkp->unlockFail.value.ui32 = stats->unlockFail;
+ bkp->lock.value.ui32 = stats->lock[FALSE];
+ bkp->lockFail.value.ui32 = stats->lockFail[FALSE];
+ bkp->unlock.value.ui32 = stats->unlock[FALSE];
+ bkp->unlockFail.value.ui32 = stats->unlockFail[FALSE];
bkp->target.value.ui32 = stats->target;
bkp->targetFail.value.ui32 = stats->targetFail;
for (i = 0; i < BALLOON_PAGE_ALLOC_TYPES_NR; i++) {
bkp->primAlloc[i].value.ui32 = stats->primAlloc[i];
bkp->primAllocFail[i].value.ui32 = stats->primAllocFail[i];
}
- bkp->primFree.value.ui32 = stats->primFree;
- bkp->primErrorPageAlloc.value.ui32 = stats->primErrorPageAlloc;
- bkp->primErrorPageFree.value.ui32 = stats->primErrorPageFree;
+ bkp->primFree.value.ui32 = stats->primFree[FALSE];
+ bkp->primErrorPageAlloc.value.ui32 = stats->primErrorPageAlloc[FALSE];
+ bkp->primErrorPageFree.value.ui32 = stats->primErrorPageFree[FALSE];
return 0;
}
@@ -152,10 +152,14 @@ BalloonKstatCreate(void)
kstat_named_init(&bkp->unlockFail, "unlockFail", KSTAT_DATA_UINT32);
kstat_named_init(&bkp->target, "target", KSTAT_DATA_UINT32);
kstat_named_init(&bkp->targetFail, "targetFail", KSTAT_DATA_UINT32);
+ kstat_named_init(&bkp->primAlloc[BALLOON_PAGE_ALLOC_LPAGE],
+ "primAllocLPage", KSTAT_DATA_UINT32);
kstat_named_init(&bkp->primAlloc[BALLOON_PAGE_ALLOC_NOSLEEP],
"primAllocNoSleep", KSTAT_DATA_UINT32);
kstat_named_init(&bkp->primAlloc[BALLOON_PAGE_ALLOC_CANSLEEP],
"primAllocCanSleep", KSTAT_DATA_UINT32);
+ kstat_named_init(&bkp->primAllocFail[BALLOON_PAGE_ALLOC_LPAGE],
+ "primAllocLPageFail", KSTAT_DATA_UINT32);
kstat_named_init(&bkp->primAllocFail[BALLOON_PAGE_ALLOC_NOSLEEP],
"primAllocNoSleepFail", KSTAT_DATA_UINT32);
kstat_named_init(&bkp->primAllocFail[BALLOON_PAGE_ALLOC_CANSLEEP],
diff --git a/open-vm-tools/scripts/common/vm-support b/open-vm-tools/scripts/common/vm-support
index 4fe94ba7..a16320e1 100644
--- a/open-vm-tools/scripts/common/vm-support
+++ b/open-vm-tools/scripts/common/vm-support
@@ -23,7 +23,7 @@ usage()
echo ""
echo "Usage: $0 [-h]"
echo " -h prints this usage statement"
- exit
+ exit 1
}
@@ -101,13 +101,13 @@ addfile()
file="$1"
if [ ! -e "$file" ]; then
- return
+ return 2
fi
dir=`dirname "$file"`
checkOutputDir "$dir"
if [ $? != 0 ]; then
- return
+ return $?
fi
# Ignore stdout and handle errors.
@@ -205,7 +205,9 @@ stageLinux()
runcmd "/tmp/modules.txt" /sbin/lsmod
runcmd "/tmp/uname.txt" uname -a
runcmd "/tmp/issue.txt" cat /etc/issue
- runcmd "/tmp/rpm-qa.txt" rpm -qa
+ if which rpm &> /dev/null; then
+ runcmd "/tmp/rpm-qa.txt" rpm -qa
+ fi
runcmd "/tmp/netstat-lan.txt" netstat -lan
runcmd "/tmp/route.txt" route
runcmd "/tmp/free.txt" free
@@ -256,7 +258,7 @@ cleanup()
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
TARFILE=vm-`date +%Y-%m-%d`.$$.tar.gz
-VER=0.90
+VER=0.92
# Parse args
for option in $@
@@ -283,7 +285,7 @@ banner "VMware UNIX Support Script $VER"
# Check for root privledge
if [ `whoami` != 'root' ]; then
- banner "You are not root, some system information can't be collected."
+ error "Please re-run this program as root. "
fi
# Source /etc/profile. If we can't find it, it's the users problem to get
@@ -318,7 +320,7 @@ if [ $? != 0 ]; then
fi
# Cleanup our temp folder if the process is signalled midway.
-trap "cleanup 1" SIGHUP SIGINT SIGQUIT SIGTERM SIGABRT
+trap "cleanup 1" HUP INT QUIT TERM ABRT
banner "Collecting support information..."
@@ -330,6 +332,7 @@ addfiles /var/log/boot*
addfiles /var/log/secure*
addfiles /var/log/messages*
addfiles /var/log/syslog*
+addfiles /var/log/vmware-*
addfiles /var/run/vmware-*
runcmd "/tmp/df.txt" df
@@ -370,7 +373,7 @@ if [ $? != 0 ]; then
fi
# Clean up temporary files
-trap - SIGHUP SIGINT SIGQUIT SIGTERM SIGABRT; cleanup
+trap - HUP INT QUIT TERM ABRT; cleanup
banner "Uploading archive to host..."
vmware-xferlogs enc $TARFILE 2>/dev/null
diff --git a/open-vm-tools/scripts/linux/pam.d/vmtoolsd b/open-vm-tools/scripts/linux/pam.d/vmtoolsd
index 4c3cfc6c..eb0599db 100644
--- a/open-vm-tools/scripts/linux/pam.d/vmtoolsd
+++ b/open-vm-tools/scripts/linux/pam.d/vmtoolsd
@@ -1,7 +1,7 @@
#%PAM-1.0
-auth sufficient pam_unix2.so nullok
-auth sufficient pam_unix.so shadow nullok
-auth required pam_unix_auth.so shadow nullok
+auth sufficient pam_unix2.so
+auth sufficient pam_unix.so shadow
+auth required pam_unix_auth.so shadow
account sufficient pam_unix2.so
account sufficient pam_unix.so
account required pam_unix_acct.so
diff --git a/open-vm-tools/services/plugins/desktopEvents/x11Lock.c b/open-vm-tools/services/plugins/desktopEvents/x11Lock.c
index 993c2f8f..b70f5915 100644
--- a/open-vm-tools/services/plugins/desktopEvents/x11Lock.c
+++ b/open-vm-tools/services/plugins/desktopEvents/x11Lock.c
@@ -347,7 +347,7 @@ X11Lock_Init(ToolsAppCtx *ctx,
int argc = 0;
char *argv[] = { NULL, NULL };
- if (strcmp(ctx->name, VMTOOLS_USER_SERVICE) != 0) {
+ if (!TOOLS_IS_USER_SERVICE(ctx)) {
VMTOOLSAPP_ERROR(ctx, EXIT_FAILURE);
return FALSE;
}
diff --git a/open-vm-tools/services/plugins/dndcp/copyPasteDnDWrapper.cpp b/open-vm-tools/services/plugins/dndcp/copyPasteDnDWrapper.cpp
index 526661f2..73211023 100644
--- a/open-vm-tools/services/plugins/dndcp/copyPasteDnDWrapper.cpp
+++ b/open-vm-tools/services/plugins/dndcp/copyPasteDnDWrapper.cpp
@@ -489,7 +489,7 @@ CopyPasteDnDWrapper::OnResetInternal()
strlen("dnd.is.active"), &reply, &replyLen) &&
(1 == atoi(reply))) {
g_debug("%s: ignore reset while file transfer is busy.\n", __FUNCTION__);
- return;
+ goto exit;
}
if (IsDnDRegistered()) {
@@ -508,6 +508,9 @@ CopyPasteDnDWrapper::OnResetInternal()
g_debug("%s: unable to reset fully DnD %d CP %d!\n",
__FUNCTION__, IsDnDRegistered(), IsCPRegistered());
}
+
+exit:
+ free(reply);
}
@@ -544,7 +547,7 @@ void
CopyPasteDnDWrapper::OnCapReg(gboolean set)
{
g_debug("%s: enter\n", __FUNCTION__);
- char *reply;
+ char *reply = NULL;
size_t replyLen;
const char *toolsDnDVersion = TOOLS_DND_VERSION_4;
char *toolsCopyPasteVersion = NULL;
@@ -593,6 +596,7 @@ CopyPasteDnDWrapper::OnCapReg(gboolean set)
}
}
vm_free(reply);
+ reply = NULL;
}
/*
diff --git a/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp b/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp
index a1b9dbe1..1762ac68 100644
--- a/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp
+++ b/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp
@@ -1328,7 +1328,7 @@ CopyPasteUIX11::LocalPrepareFileContents(const CPClipboard *clip) // IN
CPFileContentsList *contentsList = NULL;
size_t nFiles = 0;
CPFileItem *fileItem = NULL;
- Unicode tempDir = NULL;
+ char *tempDir = NULL;
size_t i = 0;
bool ret = false;
diff --git a/open-vm-tools/services/plugins/dndcp/dnd/dnd.h b/open-vm-tools/services/plugins/dndcp/dnd/dnd.h
index 7e552530..3594c729 100644
--- a/open-vm-tools/services/plugins/dndcp/dnd/dnd.h
+++ b/open-vm-tools/services/plugins/dndcp/dnd/dnd.h
@@ -91,7 +91,7 @@
#define DRAG_LEAVE_TIMEOUT 500
/* Guest detection window width and height. */
-#define DRAG_DET_WINDOW_WIDTH 15
+#define DRAG_DET_WINDOW_WIDTH 31
/* Clipboard image size limit. */
#define CLIPBOARD_IMAGE_MAX_WIDTH 4000
@@ -200,16 +200,19 @@ typedef struct DnDBlockControl {
} DnDBlockControl;
#ifdef _WIN32
+#ifdef METRO
+DECLARE_HANDLE(HDROP);
+#endif
/*
* Windows-specific functions
*/
-Unicode DnD_GetClipboardFormatName(UINT cf);
-HGLOBAL DnD_CopyStringToGlobal(ConstUnicode str);
+char *DnD_GetClipboardFormatName(UINT cf);
+HGLOBAL DnD_CopyStringToGlobal(const char *str);
HGLOBAL DnD_CopyDWORDToGlobal(DWORD *pDWORD);
-HGLOBAL DnD_CreateHDrop(ConstUnicode path, ConstUnicode fileList);
-HGLOBAL DnD_CreateHDropForGuest(ConstUnicode path,
- ConstUnicode fileList);
-size_t DnD_CPStringToLocalString(ConstUnicode bufIn,
+HGLOBAL DnD_CreateHDrop(const char *path, const char *fileList);
+HGLOBAL DnD_CreateHDropForGuest(const char *path,
+ const char *fileList);
+size_t DnD_CPStringToLocalString(const char *bufIn,
utf16_t **bufOut);
size_t DnD_LocalStringToCPString(utf16_t *bufIn,
char **bufOut);
@@ -231,7 +234,7 @@ Bool DnD_PNGToLocalFormat(const unsigned char *pngData,
Bool DnD_FakeMouseEvent(DWORD flag);
Bool DnD_FakeMouseState(DWORD key, Bool isDown);
Bool DnD_FakeEscapeKey(void);
-Bool DnD_DeleteLocalDirectory(ConstUnicode localDir);
+Bool DnD_DeleteLocalDirectory(const char *localDir);
Bool DnD_SetClipboard(UINT format, char *buffer, int len);
Bool DnD_GetFileList(HDROP hDrop,
char **remoteFiles,
@@ -254,17 +257,16 @@ Bool DnD_UriIsNonFileSchemes(char const *uri);
/*
* Shared functions
*/
-ConstUnicode DnD_GetFileRoot(void);
+const char *DnD_GetFileRoot(void);
char *DnD_CreateStagingDirectory(void);
-Bool DnD_DeleteStagingFiles(ConstUnicode stagingDir, Bool onReboot);
-Bool DnD_PrependFileRoot(ConstUnicode fileRoot, char **src, size_t *srcSize);
+Bool DnD_DeleteStagingFiles(const char *stagingDir, Bool onReboot);
int DnD_LegacyConvertToCPName(const char *nameIn,
size_t bufOutSize,
char *bufOut);
Bool DnD_CPNameListToDynBufArray(char *fileList,
size_t listSize,
DynBufArray *dynBufArray);
-Unicode DnD_GetLastDirName(const char *str);
+char *DnD_GetLastDirName(const char *str);
/* vmblock support functions. */
Bool DnD_InitializeBlocking(DnDBlockControl *blkCtrl);
diff --git a/open-vm-tools/services/plugins/dndcp/dnd/dndCPMsgV4.c b/open-vm-tools/services/plugins/dndcp/dnd/dndCPMsgV4.c
index e0c14f90..a8ce267e 100644
--- a/open-vm-tools/services/plugins/dndcp/dnd/dndCPMsgV4.c
+++ b/open-vm-tools/services/plugins/dndcp/dnd/dndCPMsgV4.c
@@ -80,7 +80,7 @@ void
DnDCPMsgV4_Init(DnDCPMsgV4 *msg)
{
ASSERT(msg);
- memset(msg, 0, sizeof(DnDCPMsgV4));
+ memset(msg, 0, sizeof *msg);
}
/**
diff --git a/open-vm-tools/services/plugins/dndcp/dnd/dndCommon.c b/open-vm-tools/services/plugins/dndcp/dnd/dndCommon.c
index 63123635..7e553196 100644
--- a/open-vm-tools/services/plugins/dndcp/dnd/dndCommon.c
+++ b/open-vm-tools/services/plugins/dndcp/dnd/dndCommon.c
@@ -48,7 +48,9 @@
#define WIN_DIRSEPC '\\'
#define WIN_DIRSEPS "\\"
-static ConstUnicode DnDCreateRootStagingDirectory(void);
+
+#ifndef DND_IS_XDG
+static const char *DnDCreateRootStagingDirectory(void);
/*
*-----------------------------------------------------------------------------
@@ -78,14 +80,14 @@ static ConstUnicode DnDCreateRootStagingDirectory(void);
*-----------------------------------------------------------------------------
*/
-Unicode
+char *
DnD_CreateStagingDirectory(void)
{
- ConstUnicode root;
- Unicode *stagingDirList;
+ const char *root;
+ char **stagingDirList;
int numStagingDirs;
int i;
- Unicode ret = NULL;
+ char *ret = NULL;
Bool found = FALSE;
/*
@@ -105,7 +107,7 @@ DnD_CreateStagingDirectory(void)
for (i = 0; i < numStagingDirs; i++) {
if (!found) {
- Unicode stagingDir;
+ char *stagingDir;
stagingDir = Unicode_Append(root, stagingDirList[i]);
@@ -119,11 +121,11 @@ DnD_CreateStagingDirectory(void)
found = TRUE;
}
- Unicode_Free(stagingDir);
+ free(stagingDir);
}
}
- Unicode_FreeList(stagingDirList, numStagingDirs);
+ Util_FreeStringList(stagingDirList, numStagingDirs);
/* Only create a directory if we didn't find one above. */
if (!found) {
@@ -132,14 +134,14 @@ DnD_CreateStagingDirectory(void)
context = Random_QuickSeed((unsigned)time(NULL));
for (i = 0; i < 10; i++) {
- Unicode temp;
+ char *temp;
/* Each staging directory is given a random name. */
- Unicode_Free(ret);
+ free(ret);
temp = Unicode_Format("%08x%c", Random_Quick(context), DIRSEPC);
VERIFY(temp);
ret = Unicode_Append(root, temp);
- Unicode_Free(temp);
+ free(temp);
if (File_CreateDirectory(ret) &&
DnDSetPermissionsOnStagingDir(ret)) {
@@ -153,12 +155,13 @@ DnD_CreateStagingDirectory(void)
exit:
if (!found && ret != NULL) {
- Unicode_Free(ret);
+ free(ret);
ret = NULL;
}
return ret;
}
+#endif // ifndef DND_IS_XDG
/*
@@ -179,8 +182,8 @@ exit:
*/
Bool
-DnD_DeleteStagingFiles(ConstUnicode stagingDir, // IN:
- Bool onReboot) // IN:
+DnD_DeleteStagingFiles(const char *stagingDir, // IN:
+ Bool onReboot) // IN:
{
Bool ret = TRUE;
@@ -202,8 +205,8 @@ DnD_DeleteStagingFiles(ConstUnicode stagingDir, // IN:
} else {
int i;
int numFiles;
- Unicode base;
- Unicode *fileList = NULL;
+ char *base;
+ char **fileList = NULL;
/* get list of files in current directory */
numFiles = File_ListDirectory(stagingDir, &fileList);
@@ -216,7 +219,7 @@ DnD_DeleteStagingFiles(ConstUnicode stagingDir, // IN:
base = Unicode_Append(stagingDir, DIRSEPS);
for (i = 0; i < numFiles; i++) {
- Unicode curPath;
+ char *curPath;
curPath = Unicode_Append(base, fileList[i]);
@@ -230,15 +233,17 @@ DnD_DeleteStagingFiles(ConstUnicode stagingDir, // IN:
}
}
- Unicode_Free(curPath);
+ free(curPath);
}
- Unicode_Free(base);
+ free(base);
}
return ret;
}
+
+#ifndef DND_IS_XDG
/*
*----------------------------------------------------------------------------
*
@@ -256,10 +261,10 @@ DnD_DeleteStagingFiles(ConstUnicode stagingDir, // IN:
*----------------------------------------------------------------------------
*/
-static ConstUnicode
+static const char *
DnDCreateRootStagingDirectory(void)
{
- ConstUnicode root;
+ const char *root;
/*
* DnD_GetFileRoot() gives us a pointer to a static string, so there's no
@@ -289,120 +294,7 @@ DnDCreateRootStagingDirectory(void)
return root;
}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * DnDPrependFileRoot --
- *
- * Given a buffer of '\0' delimited filenames, this prepends the file root
- * to each one and uses delimiter for delimiting the output buffer. The
- * buffer pointed to by *src will be freed and *src will point to a new
- * buffer containing the results. *srcSize is set to the size of the new
- * buffer, not including the NUL-terminator.
- *
- * The logic here and in the called functions appears to be UTF8-safe.
- *
- * Results:
- * TRUE on success, FALSE on failure.
- *
- * Side effects:
- * *src will be freed, and a new buffer will be allocated. This buffer must
- * be freed by the caller.
- *
- *----------------------------------------------------------------------------
- */
-
-Bool
-DnDPrependFileRoot(ConstUnicode fileRoot, // IN : file root to append
- char delimiter, // IN : delimiter for output buffer
- char **src, // IN/OUT: NUL-delimited list of paths
- size_t *srcSize) // IN/OUT: size of list
-{
- char *newData = NULL;
- size_t newDataLen = 0;
- Bool firstPass = TRUE;
- const char *begin;
- const char *end;
- const char *next;
- size_t rootLen;
- int len;
-
- ASSERT(fileRoot);
- ASSERT(src);
- ASSERT(*src);
- ASSERT(srcSize);
-
- rootLen = strlen(fileRoot);
-
- /*
- * To prevent CPName_GetComponent() errors, we set begin to the first
- * Non-NUL character in *src, and end to the last NUL character in *src. We
- * assume that the components are delimited with single NUL characters; if
- * that is not true, CPName_GetComponent() will fail.
- */
-
- for (begin = *src; *begin == '\0'; begin++)
- ;
- end = CPNameUtil_Strrchr(*src, *srcSize, '\0');
-
- /* Get the length of this component, and a pointer to the next */
- while ((len = CPName_GetComponent(begin, end, &next)) != 0) {
- size_t origNewDataLen = newDataLen;
- int escapedLen;
-
- if (len < 0) {
- Log("%s: error getting next component\n", __FUNCTION__);
- if (!firstPass) {
- free(newData);
- }
-
- return FALSE;
- }
-
- /*
- * Append this component to our list: allocate one more for NUL on first
- * pass and delimiter on all other passes.
- */
-
- escapedLen = HgfsEscape_GetSize(begin, len);
- if (escapedLen < 0) {
- Log("%s: error calculating buffer size\n", __FUNCTION__);
- return FALSE;
- } else if (0 == escapedLen) {
- newDataLen += rootLen + len + 1;
- newData = (char *)Util_SafeRealloc(newData, newDataLen);
-
- if (!firstPass) {
- ASSERT(origNewDataLen > 0);
- newData[origNewDataLen - 1] = delimiter;
- }
- memcpy(newData + origNewDataLen, fileRoot, rootLen);
- memcpy(newData + origNewDataLen + rootLen, begin, len);
- } else {
- newDataLen += rootLen + 1;
- newData = (char *)Util_SafeRealloc(newData, newDataLen);
-
- if (!firstPass) {
- ASSERT(origNewDataLen > 0);
- newData[origNewDataLen - 1] = delimiter;
- }
- memcpy(newData + origNewDataLen, fileRoot, rootLen);
- HgfsEscape_Do(begin, len, escapedLen, newData + origNewDataLen + rootLen);
- }
- newData[newDataLen - 1] = '\0';
-
- firstPass = FALSE;
- begin = next;
- }
-
- free(*src);
- *src = newData;
- /* Not including NUL terminator */
- *srcSize = newDataLen - 1;
- return TRUE;
-}
+#endif // ifndef DND_IS_XDG
/*
@@ -473,7 +365,7 @@ DnD_LegacyConvertToCPName(const char *nameIn, // IN: Buffer to convert
nameSize = strlen(nameIn);
fullNameSize = partialNameLen + partialNameSuffixLen + nameSize;
- fullName = (char *)Util_SafeMalloc(fullNameSize + 1);
+ fullName = Util_SafeMalloc(fullNameSize + 1);
memcpy(fullName, partialName, partialNameLen);
memcpy(fullName + partialNameLen, partialNameSuffix, partialNameSuffixLen);
@@ -639,7 +531,7 @@ error:
* Try to get last directory name from a full path name.
*
* Results:
- * The allocated Unicode string, or NULL on failure.
+ * The allocated UTF8 string, or NULL on failure.
*
* Side effects:
* None.
@@ -647,8 +539,8 @@ error:
*-----------------------------------------------------------------------------
*/
-Unicode
-DnD_GetLastDirName(ConstUnicode str) // IN
+char *
+DnD_GetLastDirName(const char *str) // IN
{
size_t end = strlen(str);
size_t start;
@@ -779,8 +671,7 @@ DnD_TransportBufGetPacket(DnDTransportBuffer *buf, // IN/OUT
payloadSize = buf->totalSize - buf->offset;
}
- *packet = (DnDTransportPacketHeader *)Util_SafeMalloc(
- payloadSize + DND_TRANSPORT_PACKET_HEADER_SIZE);
+ *packet = Util_SafeMalloc(payloadSize + DND_TRANSPORT_PACKET_HEADER_SIZE);
(*packet)->type = DND_TRANSPORT_PACKET_TYPE_PAYLOAD;
(*packet)->seqNum = buf->seqNum;
(*packet)->totalSize = buf->totalSize;
@@ -904,7 +795,7 @@ DnD_TransportMsgToPacket(uint8 *msg, // IN
packetSize = msgSize + DND_TRANSPORT_PACKET_HEADER_SIZE;
- *packet = (DnDTransportPacketHeader *)Util_SafeMalloc(packetSize);
+ *packet = Util_SafeMalloc(packetSize);
(*packet)->type = DND_TRANSPORT_PACKET_TYPE_SINGLE;
(*packet)->seqNum = seqNum;
@@ -940,8 +831,7 @@ size_t
DnD_TransportReqPacket(DnDTransportBuffer *buf, // IN
DnDTransportPacketHeader **packet) // OUT
{
- *packet = (DnDTransportPacketHeader *)Util_SafeMalloc(
- DND_TRANSPORT_PACKET_HEADER_SIZE);
+ *packet = Util_SafeMalloc(DND_TRANSPORT_PACKET_HEADER_SIZE);
(*packet)->type = DND_TRANSPORT_PACKET_TYPE_REQUEST;
(*packet)->seqNum = buf->seqNum;
diff --git a/open-vm-tools/services/plugins/dndcp/dnd/dndInt.h b/open-vm-tools/services/plugins/dndcp/dnd/dndInt.h
index 7eff18d7..7fa26b05 100644
--- a/open-vm-tools/services/plugins/dndcp/dnd/dndInt.h
+++ b/open-vm-tools/services/plugins/dndcp/dnd/dndInt.h
@@ -37,18 +37,13 @@ Bool DnDDataContainsIllegalCharacters(const char *data,
const size_t dataSize,
const char *illegalChars);
-Bool DnDPrependFileRoot(ConstUnicode fileRoot,
- char delimiter,
- char **src,
- size_t *srcSize);
+Bool DnDRootDirUsable(const char *pathName);
-Bool DnDRootDirUsable(ConstUnicode pathName);
+Bool DnDSetPermissionsOnRootDir(const char *pathName);
-Bool DnDSetPermissionsOnRootDir(ConstUnicode pathName);
+Bool DnDStagingDirectoryUsable(const char *pathName);
-Bool DnDStagingDirectoryUsable(ConstUnicode pathName);
-
-Bool DnDSetPermissionsOnStagingDir(ConstUnicode pathName);
+Bool DnDSetPermissionsOnStagingDir(const char *pathName);
Bool DnDReadBuffer(BufRead *b, void *out, size_t len);
diff --git a/open-vm-tools/services/plugins/dndcp/dnd/dndLinux.c b/open-vm-tools/services/plugins/dndcp/dnd/dndLinux.c
index 0b07aa6d..133219c8 100644
--- a/open-vm-tools/services/plugins/dndcp/dnd/dndLinux.c
+++ b/open-vm-tools/services/plugins/dndcp/dnd/dndLinux.c
@@ -80,7 +80,7 @@
*-----------------------------------------------------------------------------
*/
-ConstUnicode
+const char *
DnD_GetFileRoot(void)
{
return "/tmp/VMwareDnD/";
@@ -88,41 +88,6 @@ DnD_GetFileRoot(void)
/*
- *-----------------------------------------------------------------------------
- *
- * DnD_PrependFileRoot --
- *
- * Given a buffer of '\0' delimited filenames, this prepends the file root
- * to each one and uses '\0' delimiting for the output buffer. The buffer
- * pointed to by *src will be freed and *src will point to a new buffer
- * containing the results. *srcSize is set to the size of the new buffer,
- * not including the NUL-terminator.
- *
- * Results:
- * TRUE on success, FALSE on failure.
- *
- * Side effects:
- * *src will be freed, and a new buffer will be allocated. This buffer must
- * be freed by the caller.
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-DnD_PrependFileRoot(const char *fileRoot, // IN : file root to append
- char **src, // IN/OUT: NUL-delimited list of paths
- size_t *srcSize) // IN/OUT: size of list
-{
- ASSERT(fileRoot);
- ASSERT(src);
- ASSERT(*src);
- ASSERT(srcSize);
-
- return DnDPrependFileRoot(fileRoot, '\0', src, srcSize);
-}
-
-
-/*
*----------------------------------------------------------------------------
*
* DnDUriListGetFile --
@@ -792,7 +757,7 @@ DnD_CompleteBlockInitialization(int fd, // IN
*/
Bool
-DnDRootDirUsable(ConstUnicode pathName) // IN:
+DnDRootDirUsable(const char *pathName) // IN:
{
struct stat buf;
@@ -825,7 +790,7 @@ DnDRootDirUsable(ConstUnicode pathName) // IN:
*/
Bool
-DnDSetPermissionsOnRootDir(ConstUnicode pathName) // IN:
+DnDSetPermissionsOnRootDir(const char *pathName) // IN:
{
return Posix_Chmod(pathName, S_ISVTX | DND_ROOTDIR_PERMS) == 0;
}
@@ -850,7 +815,7 @@ DnDSetPermissionsOnRootDir(ConstUnicode pathName) // IN:
*/
Bool
-DnDStagingDirectoryUsable(ConstUnicode pathName) // IN:
+DnDStagingDirectoryUsable(const char *pathName) // IN:
{
struct stat buf;
@@ -879,7 +844,7 @@ DnDStagingDirectoryUsable(ConstUnicode pathName) // IN:
*/
Bool
-DnDSetPermissionsOnStagingDir(ConstUnicode pathName) // IN:
+DnDSetPermissionsOnStagingDir(const char *pathName) // IN:
{
return Posix_Chmod(pathName, DND_STAGINGDIR_PERMS) == 0;
}
diff --git a/open-vm-tools/services/plugins/dndcp/dnd/dndMsg.c b/open-vm-tools/services/plugins/dndcp/dnd/dndMsg.c
index 44f57c9d..2bd5be4c 100644
--- a/open-vm-tools/services/plugins/dndcp/dnd/dndMsg.c
+++ b/open-vm-tools/services/plugins/dndcp/dnd/dndMsg.c
@@ -473,16 +473,16 @@ DnDMsg_UnserializeArgs(DnDMsg *msg, // IN/OUT: the message
goto err;
}
readArgsSz += argSz + sizeof (uint32);
+
free(data);
+ data = NULL;
}
ASSERT(ret == DNDMSG_SUCCESS);
return ret;
err:
- if (data) {
- free(data);
- }
+ free(data);
count = DynBufArray_Count(&msg->args);
for (i = 0; i < count; ++i) {
diff --git a/open-vm-tools/services/plugins/dndcp/dndUIX11.cpp b/open-vm-tools/services/plugins/dndcp/dndUIX11.cpp
index 78f941ea..97980828 100644
--- a/open-vm-tools/services/plugins/dndcp/dndUIX11.cpp
+++ b/open-vm-tools/services/plugins/dndcp/dndUIX11.cpp
@@ -46,6 +46,7 @@ extern "C" {
#include "dndClipboard.h"
#include "dndMsg.h"
#include "file.h"
+#include "hgfsUri.h"
#include "hostinfo.h"
#include "rpcout.h"
#include "vmblock.h"
@@ -1423,6 +1424,11 @@ DnDUIX11::SetCPClipboardFromGtk(const Gtk::SelectionData& sd) // IN
g_debug("%s: Adding newPath '%s' newRelPath '%s'\n", __FUNCTION__,
newPath, newRelPath);
fileList.AddFile(newPath, newRelPath);
+#if defined(linux)
+ char *newUri = HgfsUri_ConvertFromPathToHgfsUri(newPath, false);
+ fileList.AddFileUri(newUri);
+ free(newUri);
+#endif
free(newPath);
}
@@ -1433,6 +1439,13 @@ DnDUIX11::SetCPClipboardFromGtk(const Gtk::SelectionData& sd) // IN
DynBuf_GetSize(&buf));
}
DynBuf_Destroy(&buf);
+#if defined(linux)
+ if (fileList.ToUriClipboard(&buf)) {
+ CPClipboard_SetItem(&mClipboard, CPFORMAT_FILELIST_URI, DynBuf_Get(&buf),
+ DynBuf_GetSize(&buf));
+ }
+ DynBuf_Destroy(&buf);
+#endif
return true;
}
@@ -2157,7 +2170,7 @@ DnDUIX11::WriteFileContentsToStagingDir()
CPFileContentsList *contentsList = NULL;
size_t nFiles = 0;
CPFileItem *fileItem = NULL;
- Unicode tempDir = NULL;
+ char *tempDir = NULL;
size_t i = 0;
bool ret = false;
diff --git a/open-vm-tools/services/plugins/dndcp/stringxx/autoCPtr.hh b/open-vm-tools/services/plugins/dndcp/stringxx/autoCPtr.hh
new file mode 100644
index 00000000..e1f90344
--- /dev/null
+++ b/open-vm-tools/services/plugins/dndcp/stringxx/autoCPtr.hh
@@ -0,0 +1,95 @@
+/*********************************************************
+ * Copyright (C) 2014 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * autoCPtr.hh --
+ *
+ * A simple, std::auto_ptr-like class for managing memory usually
+ * allocated by C functions.
+ *
+ * Unlike std::auto_ptr, allows providing a customer deleter and disallows
+ * copying. This is basically a wanna-be std::unique_ptr for platforms
+ * that don't have C++11 available yet.
+ *
+ * XXX: When everything uses C++11, this can be replaced with
+ * std::unique_ptr.
+ */
+
+#ifndef AUTOCPTR_HH
+#define AUTOCPTR_HH
+
+#include <cstdlib>
+#include <utility>
+
+
+template<typename T, typename FreeFunc = void (*)(void*)>
+class AutoCPtr
+{
+private:
+ typedef AutoCPtr<T, FreeFunc> SelfType;
+
+public:
+ AutoCPtr(T* p = NULL, // IN/OPT
+ FreeFunc f = std::free) // IN/OPT
+ : mP(p),
+ mFree(f)
+ {
+ }
+
+ ~AutoCPtr() { mFree(mP); }
+
+ void reset(T* p = NULL) // IN/OPT
+ {
+ if (p == mP) {
+ return;
+ }
+
+ SelfType copy(mP, mFree);
+ mP = p;
+ }
+
+ T* release()
+ {
+ T* p = mP;
+ mP = NULL;
+ return p;
+ }
+
+ T* get() const { return mP; }
+ T* operator->() const { return mP; }
+ T& operator*() const { return *mP; }
+
+ void swap(SelfType& other) // IN/OUT
+ {
+ using std::swap;
+ swap(mP, other.mP);
+ swap(mFree, other.mFree);
+ }
+
+private:
+ T* mP;
+ FreeFunc mFree;
+
+private:
+ // Non-copyable.
+ AutoCPtr(const SelfType&);
+ SelfType& operator=(const SelfType&);
+};
+
+
+#endif // AUTOCPTR_HH
diff --git a/open-vm-tools/services/plugins/dndcp/stringxx/string.cc b/open-vm-tools/services/plugins/dndcp/stringxx/string.cc
index b1939705..c4e0ba35 100644
--- a/open-vm-tools/services/plugins/dndcp/stringxx/string.cc
+++ b/open-vm-tools/services/plugins/dndcp/stringxx/string.cc
@@ -28,10 +28,12 @@
#include <sstream>
#include <iostream>
+#include "autoCPtr.hh"
#include "string.hh"
#include "unicode.h"
#include "util.h"
+
namespace utf {
/*
@@ -84,13 +86,13 @@ string::string()
*-----------------------------------------------------------------------------
*/
-string::string(ConstUnicode s) // IN
+string::string(const char *s) // IN
: mUstr(),
mUtf16Cache(NULL),
mUtf16Length(npos)
{
ASSERT(s);
- mUstr = Unicode_GetUTF8(s);
+ mUstr = s;
ASSERT(Validate(mUstr));
}
@@ -163,16 +165,9 @@ string::string(const _bstr_t &s) // IN
return;
}
- Unicode utf8 = Unicode_AllocWithUTF16(static_cast<const utf16_t *>(s));
-
- try {
- mUstr = utf8;
- Unicode_Free(utf8);
- } catch (...) {
- Unicode_Free(utf8);
- throw;
- }
-
+ mUstr = AutoCPtr<char>(
+ Unicode_AllocWithUTF16(static_cast<const utf16_t *>(s)),
+ free).get();
ASSERT(Validate(mUstr));
}
#endif
@@ -238,16 +233,8 @@ string::string(const utf16_t *s) // IN
*/
mUtf16Cache = Unicode_UTF16Strdup(s);
- Unicode utf8 = Unicode_AllocWithUTF16(s);
-
- try {
- mUstr = utf8;
- Unicode_Free(utf8);
- } catch (...) {
- Unicode_Free(utf8);
- throw;
- }
-
+ mUstr = AutoCPtr<char>(Unicode_AllocWithUTF16(s),
+ free).get();
ASSERT(Validate(mUstr));
}
@@ -276,16 +263,8 @@ string::string(const char *s, // IN
{
ASSERT(s != NULL);
- Unicode utf8 = Unicode_Alloc(s, encoding);
-
- try {
- mUstr = utf8;
- Unicode_Free(utf8);
- } catch (...) {
- Unicode_Free(utf8);
- throw;
- }
-
+ mUstr = AutoCPtr<char>(Unicode_Alloc(s, encoding),
+ free).get();
ASSERT(Validate(mUstr));
}
@@ -486,11 +465,12 @@ string::operator+=(value_type uc) // IN
*/
void
-string::swap(string &s) // IN/OUT
+string::swap(string& s) // IN/OUT
{
+ using std::swap;
mUstr.swap(s.mUstr);
- std::swap(mUtf16Cache, s.mUtf16Cache);
- std::swap(mUtf16Length, s.mUtf16Length);
+ swap(mUtf16Cache, s.mUtf16Cache);
+ swap(mUtf16Length, s.mUtf16Length);
}
@@ -522,6 +502,29 @@ string::resize(size_type n, // IN
/*
*-----------------------------------------------------------------------------
*
+ * utf::string::reserve --
+ *
+ * Change the amount of memory allocated for the utf::string.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+string::reserve(size_type n) // IN/OPT
+{
+ mUstr.reserve(n);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* utf::string::c_str --
*
* Get the UTF-8 representation of this string.
@@ -755,10 +758,7 @@ string
string::trim()
const
{
- Unicode trim = Unicode_Trim(c_str());
- string result(trim);
- Unicode_Free(trim);
- return result;
+ return CopyAndFree(Unicode_Trim(c_str()), free);
}
@@ -782,10 +782,7 @@ string
string::trimLeft()
const
{
- Unicode trim = Unicode_TrimLeft(c_str());
- string result(trim);
- Unicode_Free(trim);
- return result;
+ return CopyAndFree(Unicode_TrimLeft(c_str()), free);
}
@@ -809,10 +806,7 @@ string
string::trimRight()
const
{
- Unicode trim = Unicode_TrimRight(c_str());
- string result(trim);
- Unicode_Free(trim);
- return result;
+ return CopyAndFree(Unicode_TrimRight(c_str()), free);
}
@@ -862,14 +856,10 @@ string::toLower(const char *locale) // IN
const
{
#ifdef USE_ICU
- Unicode lower = Unicode_ToLower(c_str(), locale);
- string results(lower);
- Unicode_Free(lower);
+ return CopyAndFree(Unicode_ToLower(c_str(), locale), free);
#else
- string results(mUstr.lowercase());
+ return mUstr.lowercase();
#endif
-
- return results;
}
@@ -895,20 +885,14 @@ string::toUpper(const char *locale) // IN
const
{
#ifdef USE_ICU
- Unicode upper = Unicode_ToUpper(c_str(), locale);
- string results(upper);
- Unicode_Free(upper);
+ return CopyAndFree(Unicode_ToUpper(c_str(), locale), free);
#else
- string results(mUstr.uppercase());
+ return mUstr.uppercase();
#endif
-
-
- return results;
}
#ifdef USE_ICU
-
/*
*-----------------------------------------------------------------------------
*
@@ -930,13 +914,8 @@ string
string::toTitle(const char *locale) // IN
const
{
- Unicode title = Unicode_ToTitle(c_str(), locale);
- string results(title);
- Unicode_Free(title);
-
- return results;
+ return CopyAndFree(Unicode_ToTitle(c_str(), locale), free);
}
-
#endif
@@ -1206,6 +1185,8 @@ string::replace(size_type i, // IN
* Mutates this string by replacing all occurrences of one string with
* another.
*
+ * Does nothing if the `from` string is empty.
+ *
* Results:
* A reference to this object.
*
@@ -1219,10 +1200,15 @@ string&
string::replace(const string& from, // IN
const string& to) // IN
{
+ if (from.empty()) {
+ return *this;
+ }
+
size_type end;
size_type start = 0;
size_type fromSize = from.length();
string result;
+ result.reserve(bytes() * to.bytes() / from.bytes());
while ((end = find(from, start)) != string::npos) {
result += substr(start, end - start);
@@ -1235,6 +1221,8 @@ string::replace(const string& from, // IN
result += substr(start);
}
+ result.reserve(0);
+
swap(result);
return *this;
}
@@ -2086,16 +2074,8 @@ CreateWithLength(const void *buffer, // IN
throw ConversionError();
}
- Unicode utf8 = Unicode_AllocWithLength(buffer, lengthInBytes, encoding);
-
- try {
- string result(utf8);
- Unicode_Free(utf8);
- return result;
- } catch (...) {
- Unicode_Free(utf8);
- throw;
- }
+ return CopyAndFree(Unicode_AllocWithLength(buffer, lengthInBytes, encoding),
+ free);
}
@@ -2152,6 +2132,32 @@ CreateWithBOMBuffer(const void *buffer, // IN
/*
+ *----------------------------------------------------------------------
+ *
+ * utf::CopyAndFree --
+ *
+ * Creates a utf::string from an allocated UTF-8 C string,
+ * automatically freeing it afterward.
+ *
+ * Results:
+ * A copy of the string.
+ *
+ * Side Effect:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+string
+CopyAndFree(char* utf8, // IN
+ void (*freeFunc)(void*)) // IN/OPT
+{
+ ASSERT(utf8 != NULL);
+ return AutoCPtr<char>(utf8, freeFunc).get();
+}
+
+
+/*
*-----------------------------------------------------------------------------
*
* utf::IntToStr --
diff --git a/open-vm-tools/services/plugins/dndcp/stringxx/string.hh b/open-vm-tools/services/plugins/dndcp/stringxx/string.hh
index dda369f6..138610f8 100644
--- a/open-vm-tools/services/plugins/dndcp/stringxx/string.hh
+++ b/open-vm-tools/services/plugins/dndcp/stringxx/string.hh
@@ -98,7 +98,7 @@ public:
} NormalizeMode;
string();
- string(ConstUnicode s);
+ string(const char *s);
#ifdef _WIN32
string(const ubstr_t &s);
@@ -127,6 +127,7 @@ public:
// Mapping functions to Glib::ustring
void swap(string &s);
void resize(size_type n, value_type c = '\0');
+ void reserve(size_type n = 0);
bool empty() const;
size_type size() const;
size_type w_size() const;
@@ -233,42 +234,42 @@ private:
// Helper operators
string inline
-operator+(ConstUnicode lhs, const string &rhs) {
+operator+(const char *lhs, const string &rhs) {
return string(lhs) + rhs;
}
string inline
-operator+(const string& lhs, ConstUnicode rhs) {
+operator+(const string& lhs, const char *rhs) {
return lhs + string(rhs);
}
bool inline
-operator==(ConstUnicode lhs, const string &rhs) {
+operator==(const char *lhs, const string &rhs) {
return string(lhs) == rhs;
}
bool inline
-operator!=(ConstUnicode lhs, const string &rhs) {
+operator!=(const char *lhs, const string &rhs) {
return string(lhs) != rhs;
}
bool inline
-operator<(ConstUnicode lhs, const string &rhs) {
+operator<(const char *lhs, const string &rhs) {
return string(lhs) < rhs;
}
bool inline
-operator>(ConstUnicode lhs, const string &rhs) {
+operator>(const char *lhs, const string &rhs) {
return string(lhs) > rhs;
}
bool inline
-operator<=(ConstUnicode lhs, const string &rhs) {
+operator<=(const char *lhs, const string &rhs) {
return string(lhs) <= rhs;
}
bool inline
-operator>=(ConstUnicode lhs, const string &rhs) {
+operator>=(const char *lhs, const string &rhs) {
return string(lhs) >= rhs;
}
@@ -294,20 +295,21 @@ class ConversionError {};
// Helper functions
-bool VMSTRING_EXPORT Validate(const Glib::ustring& s);
+VMSTRING_EXPORT bool Validate(const Glib::ustring& s);
-string VMSTRING_EXPORT
+VMSTRING_EXPORT string
CreateWithLength(const void *buffer, ssize_t lengthInBytes, StringEncoding encoding);
-string VMSTRING_EXPORT
+VMSTRING_EXPORT string
CreateWithBOMBuffer(const void *buffer, ssize_t lengthInBytes);
-string VMSTRING_EXPORT
-IntToStr(int64 val);
+VMSTRING_EXPORT string CopyAndFree(char* utf8, void (*freeFunc)(void*) = free);
-void VMSTRING_EXPORT CreateWritableBuffer(const string& s,
+VMSTRING_EXPORT string IntToStr(int64 val);
+
+VMSTRING_EXPORT void CreateWritableBuffer(const string& s,
std::vector<char>& buf);
-void VMSTRING_EXPORT CreateWritableBuffer(const string& s,
+VMSTRING_EXPORT void CreateWritableBuffer(const string& s,
std::vector<utf16_t>& buf);
diff --git a/open-vm-tools/services/plugins/dndcp/stringxx/ubstr_t.hh b/open-vm-tools/services/plugins/dndcp/stringxx/ubstr_t.hh
index b0498f93..e8031340 100644
--- a/open-vm-tools/services/plugins/dndcp/stringxx/ubstr_t.hh
+++ b/open-vm-tools/services/plugins/dndcp/stringxx/ubstr_t.hh
@@ -34,6 +34,8 @@
#include <comutil.h>
#include <glibmm/refptr.h>
+#include "autoCPtr.hh"
+
extern "C" {
#include "unicode.h"
#include "util.h"
@@ -133,7 +135,10 @@ private:
// Takes ownership of the input string.
void Set(char *utf8String) // IN/OUT: May be NULL.
{
- Unicode_Free(mUTF8String);
+ if (mUTF8String == utf8String) {
+ return;
+ }
+ free(mUTF8String);
mUTF8String = utf8String;
}
@@ -146,7 +151,7 @@ private:
// Only destructible via unreference().
~UTF8Data()
{
- Unicode_Free(mUTF8String);
+ free(mUTF8String);
}
char *mUTF8String;
@@ -253,14 +258,7 @@ ubstr_t::ubstr_t(const char *s) // IN: A UTF-8-encoded string.
if (s != NULL) {
// Since we already have the UTF-8 version of the string, cache it now.
mUTF8 = Glib::RefPtr<UTF8Data>(new UTF8Data(Util_SafeStrdup(s)));
- utf16_t *utf16Str = Unicode_GetAllocUTF16(s);
- try {
- mBstr = utf16Str;
- Unicode_Free(utf16Str);
- } catch (...) {
- Unicode_Free(utf16Str);
- throw;
- }
+ mBstr = AutoCPtr<utf16_t>(Unicode_GetAllocUTF16(s), free).get();
}
}
@@ -832,19 +830,16 @@ ubstr_t::GetUTF8Cache()
return NULL;
}
- char *utf8Str = NULL;
- try {
- if (!mUTF8) {
- mUTF8 = Glib::RefPtr<UTF8Data>(new UTF8Data());
- }
+ if (!mUTF8) {
+ mUTF8 = Glib::RefPtr<UTF8Data>(new UTF8Data());
+ }
- if (mUTF8->Get() == NULL) {
- utf8Str = Unicode_AllocWithUTF16(static_cast<wchar_t *>(mBstr));
- mUTF8->Set(utf8Str);
- }
- } catch (...) {
- Unicode_Free(utf8Str);
- throw;
+ if (mUTF8->Get() == NULL) {
+ AutoCPtr<char> utf8Str(
+ Unicode_AllocWithUTF16(static_cast<wchar_t *>(mBstr)),
+ free);
+ mUTF8->Set(utf8Str.get());
+ utf8Str.release();
}
return mUTF8->Get();
diff --git a/open-vm-tools/services/plugins/dndcp/xutils/xutils.cc b/open-vm-tools/services/plugins/dndcp/xutils/xutils.cc
index 15a0c32b..db2b5426 100644
--- a/open-vm-tools/services/plugins/dndcp/xutils/xutils.cc
+++ b/open-vm-tools/services/plugins/dndcp/xutils/xutils.cc
@@ -29,6 +29,7 @@
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <gdk/gdkx.h>
+#include <cstring>
extern "C" {
#include "vm_assert.h"
diff --git a/open-vm-tools/services/plugins/grabbitmqProxy/grabbitmqProxyPlugin.c b/open-vm-tools/services/plugins/grabbitmqProxy/grabbitmqProxyPlugin.c
index 78793b71..9451dccb 100644
--- a/open-vm-tools/services/plugins/grabbitmqProxy/grabbitmqProxyPlugin.c
+++ b/open-vm-tools/services/plugins/grabbitmqProxy/grabbitmqProxyPlugin.c
@@ -998,15 +998,15 @@ VmxListenSockConnectedCb(AsyncSocket *asock, // IN
g_debug("Entering %s\n", __FUNCTION__);
- g_info("Got vmx connection, socket=%d.\n", fd);
+ g_info("Got vmx connection, socket=%d\n", fd);
if (AsyncSocket_GetState(asock) != AsyncSocketConnected) {
- g_info("Socket %d is not connected, closing.\n", fd);
+ g_info("Socket %d is not connected, closing\n", fd);
goto exit;
}
if (!AsyncSocket_SetBufferSizes(asock, sendBufSize, recvBufSize)) {
- g_info("Closing socket %d due to error.\n", fd);
+ g_info("Cannot set VSOCK buffer sizes, closing socket %d\n", fd);
goto exit;
}
@@ -1929,8 +1929,7 @@ ToolsOnLoad(ToolsAppCtx *ctx) // IN
Poll_InitGtk();
SSL_Init(GRabbitmqProxyGetSSLLibPath, NULL, NULL);
- if (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) != 0 &&
- strcmp(ctx->name, VMTOOLS_USER_SERVICE) != 0) {
+ if (!TOOLS_IS_MAIN_SERVICE(ctx) && !TOOLS_IS_USER_SERVICE(ctx)) {
g_info("Unknown container '%s', not loading grabbitmqProxyPlugin.",
ctx->name);
return NULL;
diff --git a/open-vm-tools/services/plugins/guestInfo/diskInfo.c b/open-vm-tools/services/plugins/guestInfo/diskInfo.c
index c682f7db..2500ff90 100644
--- a/open-vm-tools/services/plugins/guestInfo/diskInfo.c
+++ b/open-vm-tools/services/plugins/guestInfo/diskInfo.c
@@ -91,7 +91,7 @@ GuestInfoGetDiskInfoWiper(void)
/* Get partition list. */
if (!WiperPartition_Open(&pl)) {
- g_debug("GetDiskInfo: ERROR: could not get partition list\n");
+ g_warning("GetDiskInfo: ERROR: could not get partition list\n");
return FALSE;
}
@@ -108,13 +108,13 @@ GuestInfoGetDiskInfoWiper(void)
error = WiperSinglePartition_GetSpace(part, &freeBytes, &totalBytes);
if (strlen(error)) {
- g_debug("GetDiskInfo: ERROR: could not get space for partition %s: %s\n",
+ g_warning("GetDiskInfo: ERROR: could not get space for partition %s: %s\n",
part->mountPoint, error);
goto out;
}
if (strlen(part->mountPoint) + 1 > partNameSize) {
- g_debug("GetDiskInfo: ERROR: Partition name buffer too small\n");
+ g_warning("GetDiskInfo: ERROR: Partition name buffer too small\n");
goto out;
}
diff --git a/open-vm-tools/services/plugins/guestInfo/guestInfoInt.h b/open-vm-tools/services/plugins/guestInfo/guestInfoInt.h
index b35b3cab..f55f0486 100644
--- a/open-vm-tools/services/plugins/guestInfo/guestInfoInt.h
+++ b/open-vm-tools/services/plugins/guestInfo/guestInfoInt.h
@@ -26,14 +26,39 @@
*/
#define G_LOG_DOMAIN "guestinfo"
-#include <glib.h>
+#include "vmware/tools/log.h"
#include "nicInfo.h"
+#include "dynbuf.h"
+
+/*
+ * Internal stat IDs used by intermediate stats collected
+ * for computing derived stats.
+ *
+ * NOTE: These IDs should not be published to the host as
+ * these may change.
+ */
+#define GuestStatID_SwapSpaceUsed ((GuestStatToolsID) (GuestStatID_Max + 0))
+#define GuestStatID_SwapFilesCurrent ((GuestStatToolsID) (GuestStatID_Max + 1))
+#define GuestStatID_SwapFilesMax ((GuestStatToolsID) (GuestStatID_Max + 2))
+#define GuestStatID_Linux_LowWaterMark ((GuestStatToolsID) (GuestStatID_Max + 3))
+#define GuestStatID_Linux_MemAvailable ((GuestStatToolsID) (GuestStatID_Max + 4))
+#define GuestStatID_Linux_MemBuffers ((GuestStatToolsID) (GuestStatID_Max + 5))
+#define GuestStatID_Linux_MemCached ((GuestStatToolsID) (GuestStatID_Max + 6))
+#define GuestStatID_Linux_MemInactiveFile ((GuestStatToolsID) (GuestStatID_Max + 7))
+#define GuestStatID_Linux_MemSlabReclaim ((GuestStatToolsID) (GuestStatID_Max + 8))
+#define GuestStatID_Linux_MemTotal ((GuestStatToolsID) (GuestStatID_Max + 9))
+#define GuestStatID_Linux_Internal_Max ((GuestStatToolsID) (GuestStatID_Max + 10))
extern int guestInfoPollInterval;
Bool
-GuestInfo_PerfMon(struct GuestMemInfo *vmStats);
+GuestInfo_PerfMon(DynBuf *stats);
+
+#if defined(_WIN32)
+void
+GuestInfo_SetStatLogging(Bool isEnabled);
+#endif
GuestDiskInfo *
GuestInfoGetDiskInfoWiper(void);
diff --git a/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c b/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c
index 06ce36f6..3cb5e39a 100644
--- a/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c
+++ b/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c
@@ -60,6 +60,11 @@
#include "vmware/tools/utils.h"
#include "vmware/tools/vmbackup.h"
+#if defined(_WIN32)
+#include "guestStats.h"
+#include "win32/guestInfoWin32.h"
+#endif
+
#if !defined(__APPLE__)
#include "vm_version.h"
#include "embed_version.h"
@@ -68,13 +73,32 @@ VM_EMBED_VERSION(VMTOOLSD_VERSION_STRING);
#endif
/**
- * Default poll interval is 30s (in milliseconds).
+ * Default poll interval for guestInfo is 30s
*/
-#define GUESTINFO_TIME_INTERVAL_MSEC 30000
+#define GUESTINFO_POLL_INTERVAL 30
+
+/**
+ * Default poll interval for guestStats is 20s
+ */
+#define GUESTINFO_STATS_INTERVAL 20
#define GUESTINFO_DEFAULT_DELIMITER ' '
/*
+ * Define what guest info types and nic info versions could be sent
+ * to update nic info at VMX. The order defines a sequence of fallback
+ * paths to provide backward compatibility for ESX running with nic
+ * info version older than the guest OS.
+ */
+typedef enum NicInfoMethod {
+ NIC_INFO_V3_WITH_INFO_IPADDRESS_V3,
+ NIC_INFO_V3_WITH_INFO_IPADDRESS_V2,
+ NIC_INFO_V2_WITH_INFO_IPADDRESS_V2,
+ NIC_INFO_V1_WITH_INFO_IPADDRESS,
+ NIC_INFO_METHOD_MAX
+} NicInfoMethod;
+
+/*
* Stores information about all guest information sent to the vmx.
*/
@@ -83,6 +107,7 @@ typedef struct _GuestInfoCache {
char *value[INFO_MAX];
NicInfoV3 *nicInfo;
GuestDiskInfo *diskInfo;
+ NicInfoMethod method;
} GuestInfoCache;
@@ -93,12 +118,22 @@ typedef struct _GuestInfoCache {
*/
int guestInfoPollInterval = 0;
+/**
+ * Defines the current stats interval (in milliseconds).
+ *
+ * This value is controlled by the guestinfo.stats-interval config file option.
+ */
+int guestInfoStatsInterval = 0;
/**
- * Gather loop timeout source.
+ * GuestInfo gather loop timeout source.
*/
-static GSource *gatherTimeoutSource = NULL;
+static GSource *gatherInfoTimeoutSource = NULL;
+/**
+ * GuestStats gather loop timeout source.
+ */
+static GSource *gatherStatsTimeoutSource = NULL;
/* Local cache of the guest information that was last sent to vmx. */
static GuestInfoCache gInfoCache;
@@ -117,14 +152,17 @@ static Bool vmResumed;
*/
-static Bool GuestInfoUpdateVmdb(ToolsAppCtx *ctx, GuestInfoType infoType, void *info);
+static Bool GuestInfoUpdateVmdb(ToolsAppCtx *ctx,
+ GuestInfoType infoType,
+ void *info,
+ size_t infoSize);
static Bool SetGuestInfo(ToolsAppCtx *ctx, GuestInfoType key,
const char *value);
static void SendUptime(ToolsAppCtx *ctx);
static Bool DiskInfoChanged(const GuestDiskInfo *diskInfo);
static void GuestInfoClearCache(void);
static GuestNicList *NicInfoV3ToV2(const NicInfoV3 *infoV3);
-static void TweakGatherLoop(ToolsAppCtx *ctx, gboolean enable);
+static void TweakGatherLoops(ToolsAppCtx *ctx, gboolean enable);
/*
@@ -179,7 +217,7 @@ GuestInfoVMSupport(RpcInData *data)
vmSupportProcArgs.lpThreadAttributes = &saThread;
vmSupportProcArgs.dwCreationFlags = CREATE_NO_WINDOW;
- g_debug("Starting vm-support script - %s\n", vmSupport);
+ g_message("Starting vm-support script - %s\n", vmSupport);
vmSupportProc = ProcMgr_ExecAsync(vmSupport, &vmSupportProcArgs);
g_free(vmSupport);
@@ -196,7 +234,7 @@ GuestInfoVMSupport(RpcInData *data)
gchar *vmSupportCmdArgv[] = {"vm-support", "-u", NULL};
- g_debug("Starting vm-support script - %s\n", vmSupportCmdArgv[0]);
+ g_message("Starting vm-support script - %s\n", vmSupportCmdArgv[0]);
if (!g_spawn_async(NULL, vmSupportCmdArgv, NULL,
G_SPAWN_SEARCH_PATH |
G_SPAWN_STDOUT_TO_DEV_NULL |
@@ -237,16 +275,12 @@ GuestInfoGather(gpointer data)
GuestDiskInfo *diskInfo = NULL;
#endif
NicInfoV3 *nicInfo = NULL;
-#if (defined(__linux__) && !defined(USERWORLD)) || defined(_WIN32)
- GuestMemInfo vmStats = {0};
- gboolean perfmonEnabled;
-#endif
ToolsAppCtx *ctx = data;
g_debug("Entered guest info gather.\n");
/* Send tools version. */
- if (!GuestInfoUpdateVmdb(ctx, INFO_BUILD_NUMBER, BUILD_NUMBER)) {
+ if (!GuestInfoUpdateVmdb(ctx, INFO_BUILD_NUMBER, BUILD_NUMBER, 0)) {
/*
* An older vmx talking to new tools wont be able to handle
* this message. Continue, if thats the case.
@@ -260,7 +294,7 @@ GuestInfoGather(gpointer data)
if (osString == NULL) {
g_warning("Failed to get OS info.\n");
} else {
- if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME_FULL, osString)) {
+ if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME_FULL, osString, 0)) {
g_warning("Failed to update VMDB\n");
}
}
@@ -270,7 +304,7 @@ GuestInfoGather(gpointer data)
if (osString == NULL) {
g_warning("Failed to get OS info.\n");
} else {
- if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME, osString)) {
+ if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME, osString, 0)) {
g_warning("Failed to update VMDB\n");
}
}
@@ -284,7 +318,7 @@ GuestInfoGather(gpointer data)
if ((diskInfo = GuestInfo_GetDiskInfo()) == NULL) {
g_warning("Failed to get disk info.\n");
} else {
- if (GuestInfoUpdateVmdb(ctx, INFO_DISK_FREE_SPACE, diskInfo)) {
+ if (GuestInfoUpdateVmdb(ctx, INFO_DISK_FREE_SPACE, diskInfo, 0)) {
GuestInfo_FreeDiskInfo(gInfoCache.diskInfo);
gInfoCache.diskInfo = diskInfo;
} else {
@@ -297,7 +331,7 @@ GuestInfoGather(gpointer data)
if (!System_GetNodeName(sizeof name, name)) {
g_warning("Failed to get netbios name.\n");
- } else if (!GuestInfoUpdateVmdb(ctx, INFO_DNS_NAME, name)) {
+ } else if (!GuestInfoUpdateVmdb(ctx, INFO_DNS_NAME, name, 0)) {
g_warning("Failed to update VMDB.\n");
}
@@ -313,7 +347,7 @@ GuestInfoGather(gpointer data)
if (GuestInfo_IsEqual_NicInfoV3(nicInfo, gInfoCache.nicInfo)) {
g_debug("Nic info not changed.\n");
GuestInfo_FreeNicInfo(nicInfo);
- } else if (GuestInfoUpdateVmdb(ctx, INFO_IPADDRESS, nicInfo)) {
+ } else if (GuestInfoUpdateVmdb(ctx, INFO_IPADDRESS, nicInfo, 0)) {
/*
* Since the update succeeded, free the old cached object, and assign
* ours to the cache.
@@ -328,23 +362,59 @@ GuestInfoGather(gpointer data)
/* Send the uptime to VMX so that it can detect soft resets. */
SendUptime(ctx);
+ return TRUE;
+}
+
+
+/*
+ ******************************************************************************
+ * GuestInfoStatsGather -- */ /**
+ *
+ * Collects all the desired guest stats and updates the VMX.
+ *
+ * @param[in] data The application context.
+ *
+ * @return TRUE to indicate that the timer should be rescheduled.
+ *
+ ******************************************************************************
+ */
+
+static gboolean
+GuestInfoStatsGather(gpointer data)
+{
#if (defined(__linux__) && !defined(USERWORLD)) || defined(_WIN32)
- /* Send the vmstats to the VMX. */
- perfmonEnabled = !g_key_file_get_boolean(ctx->config,
+ ToolsAppCtx *ctx = data;
+ DynBuf stats;
+#endif
+#if defined(_WIN32)
+ gboolean perfmonLogStats;
+#endif
+
+ g_debug("Entered guest info stats gather.\n");
+
+#if defined(_WIN32)
+ perfmonLogStats = g_key_file_get_boolean(ctx->config,
CONFGROUPNAME_GUESTINFO,
- CONFNAME_GUESTINFO_DISABLEPERFMON,
+ CONFNAME_GUESTINFO_ENABLESTATLOGGING,
NULL);
- if (perfmonEnabled) {
- if (!GuestInfo_PerfMon(&vmStats)) {
- g_warning("Failed to get vmstats.\n");
- } else {
- vmStats.version = 1;
- if (!GuestInfoUpdateVmdb(ctx, INFO_MEMORY, &vmStats)) {
- g_warning("Failed to send vmstats.\n");
- }
+ GuestInfo_SetStatLogging(perfmonLogStats);
+#endif
+
+#if (defined(__linux__) && !defined(USERWORLD)) || defined(_WIN32)
+ /* Send the vmstats to the VMX. */
+ DynBuf_Init(&stats);
+
+ if (GuestInfo_PerfMon(&stats)) {
+ if (!GuestInfoUpdateVmdb(ctx, INFO_MEMORY, DynBuf_Get(&stats),
+ DynBuf_GetSize(&stats))) {
+ g_warning("Failed to send vmstats.\n");
}
+ } else {
+ g_warning("Failed to get vmstats.\n");
}
+
+ DynBuf_Destroy(&stats);
#endif
return TRUE;
@@ -426,6 +496,326 @@ GuestInfoConvertNicInfoToNicInfoV1(NicInfoV3 *info,
/*
******************************************************************************
+ * GuestInfoSendMemoryInfo -- */ /**
+ *
+ * Push memory informations about the guest to the vmx
+ *
+ * @param[in] ctx Application context.
+ * @param[in] infoSize Size of the struct to send
+ * @param[in] info Struct that contains memory info
+ *
+ * @retval TRUE Update sent successfully.
+ * @retval FALSE Had trouble with transmission.
+ *
+ ******************************************************************************
+ */
+
+static Bool
+GuestInfoSendMemoryInfo(ToolsAppCtx *ctx, // IN: Application context
+ uint64 infoSize, // IN: Size of the following struct
+ void* info) // IN: Pointer to GuestMemInfoRPC
+{
+ char *request;
+ char header[32];
+ size_t headerLen;
+ size_t requestSize;
+ Bool success = FALSE;
+
+ Str_Sprintf(header, sizeof header, "%s %d ", GUEST_INFO_COMMAND,
+ INFO_MEMORY);
+
+ headerLen = strlen(header);
+ requestSize = headerLen + infoSize;
+
+ request = g_malloc(requestSize);
+
+ if (request == NULL) {
+ g_warning("Failed to allocate GuestMemInfo memory.\n");
+ } else {
+ g_debug("Sending GuestMemInfo message.\n");
+
+ /* Yes, stomp on the NUL at the end of the header */
+ memcpy(request, header, headerLen);
+ memcpy(request + headerLen, info, infoSize);
+
+ /* Send all the information in the message. */
+ success = RpcChannel_Send(ctx->rpc, request, requestSize, NULL, NULL);
+
+ g_free(request);
+ }
+
+ if (success) {
+ g_debug("GuestMemInfo sent successfully.\n");
+ } else {
+ g_warning("Error sending GuestMemInfo.\n");
+ }
+
+ return success;
+}
+
+
+/*
+ ******************************************************************************
+ *
+ * NIC_INFO_V3_WITH_INFO_IPADDRESS_V3: Bump up the NICINFO_MAX_IPS to 2048
+ * NIC_INFO_V3_WITH_INFO_IPADDRESS_V2: NICINFO_MAX_IPS to 64
+ *
+ * The current fallback paths:
+ * +---------------+-------------------+-------------------+------------------+
+ * | | INFO_IPADDRESS_V3 | INFO_IPADDRESS_V2 | INFO_IPADDRESS |
+ * +---------------+-------------------+-------------------+------------------+
+ * | NIC_INFO_V3 | (0) | (1) | |
+ * +---------------+-------------------+-------------------+------------------+
+ * | NIC_INFO_V2 | | (2) | |
+ * +---------------+-------------------+-------------------+------------------+
+ * | NIC_INFO_V1 | | | (3) |
+ * +---------------+-------------------+-------------------+------------------+
+ *
+ ******************************************************************************
+ */
+
+
+/*
+ ******************************************************************************
+ * GuestInfoSendNicInfoXdr -- */ /**
+ *
+ * Push updated nic info to VMX using XDR data format.
+ *
+ * @param[in] ctx Application context.
+ * @param[in] message The protocol for a 'nic info' message.
+ * @param[in] type Guest information type.
+ *
+ * @retval TRUE Update sent successfully.
+ * @retval FALSE Had trouble with serialization or transmission.
+ *
+ ******************************************************************************
+ */
+
+static Bool
+GuestInfoSendNicInfoXdr(ToolsAppCtx *ctx, // IN
+ GuestNicProto *message, // IN
+ GuestInfoType type) // IN
+{
+ Bool status = FALSE;
+ XDR xdrs;
+ gchar *request;
+ char *reply = NULL;
+ size_t replyLen;
+
+ /* Add the RPC preamble: message name, and type. */
+ request = g_strdup_printf("%s %d ", GUEST_INFO_COMMAND, type);
+
+ if (DynXdr_Create(&xdrs) == NULL) {
+ goto exit;
+ }
+
+ /* Write preamble and serialized nic info to XDR stream. */
+ if (!DynXdr_AppendRaw(&xdrs, request, strlen(request)) ||
+ !xdr_GuestNicProto(&xdrs, message)) {
+ g_warning("Error serializing nic info v%d data.", message->ver);
+ } else {
+ status = RpcChannel_Send(ctx->rpc, DynXdr_Get(&xdrs), xdr_getpos(&xdrs),
+ &reply, &replyLen);
+ if (!status) {
+ g_warning("%s: update failed: request \"%s\", reply \"%s\".\n",
+ __FUNCTION__, request, reply);
+ }
+ vm_free(reply);
+ }
+ DynXdr_Destroy(&xdrs, TRUE);
+
+exit:
+ g_free(request);
+ return status;
+}
+
+
+/*
+ ******************************************************************************
+ * GuestInfoSendData -- */ /**
+ *
+ * Push GuestInfo information to the VMX. So far, it is mainly used to
+ * send the fixed nic info V1 data.
+ *
+ * @param[in] ctx Application context.
+ * @param[in] info Guest information data.
+ * @param[in] infoLength Length of guest information.
+ * @param[in] type Guest information type.
+ *
+ * @retval TRUE Update sent successfully.
+ * @retval FALSE Had trouble with transmission.
+ *
+ ******************************************************************************
+ */
+
+static Bool
+GuestInfoSendData(ToolsAppCtx *ctx, // IN
+ void *info, // IN
+ u_int infoLength, // IN
+ GuestInfoType type) // IN
+{
+ Bool status;
+ gchar *request;
+ u_int msgLength = infoLength;
+ gchar *message = NULL;
+ char *reply = NULL;
+ size_t replyLen;
+
+ /* Add the RPC preamble: message name, and type. */
+ request = g_strdup_printf("%s %d ", GUEST_INFO_COMMAND, type);
+
+ msgLength += strlen(request);
+ message = g_malloc(msgLength);
+
+ memcpy(message, request, strlen(request));
+ memcpy(message + strlen(request), info, infoLength);
+
+ status = RpcChannel_Send(ctx->rpc, message, msgLength, &reply, &replyLen);
+ if (!status) {
+ g_warning("%s: update failed: request \"%s\", reply \"%s\".\n",
+ __FUNCTION__, request, reply);
+ }
+ vm_free(reply);
+
+ g_free(message);
+ g_free(request);
+
+ return status;
+}
+
+
+/*
+ ******************************************************************************
+ * GuestNicInfoV3ToV3_64 -- */ /**
+ *
+ * New NicInfoV3 allows more IP addresses than the previous version. Preseve
+ * the backward compatibility such that NicInfoV3 with old limit could still
+ * go through without falling all the way to V2 or V1. It reduces the number
+ * of IP addresses at each interface to the previous max limit 64.
+ *
+ * @param[in] info NicInfoV3 container.
+ *
+ * @retval Pointer to a shallow copy of NicInfoV3 with reduced max IPs.
+ *
+ ******************************************************************************
+ */
+
+static NicInfoV3*
+GuestNicInfoV3ToV3_64(NicInfoV3 *info) // IN
+{
+ u_int idx;
+
+ NicInfoV3 *info64 = g_malloc(sizeof(struct NicInfoV3));
+
+ memcpy(info64, info, sizeof(struct NicInfoV3));
+ info64->nics.nics_val =
+ g_malloc(info64->nics.nics_len * sizeof(struct GuestNicV3));
+
+ for (idx = 0; idx < info64->nics.nics_len; idx++) {
+ memcpy(&info64->nics.nics_val[idx], &info->nics.nics_val[idx],
+ sizeof(struct GuestNicV3));
+
+ if (info64->nics.nics_val[idx].ips.ips_len > INFO_IPADDRESS_V2_MAX_IPS) {
+ info64->nics.nics_val[idx].ips.ips_len = INFO_IPADDRESS_V2_MAX_IPS;
+ }
+ }
+
+ return info64;
+}
+
+
+/*
+ ******************************************************************************
+ * GuestInfoSendNicInfo -- */ /**
+ *
+ * Push updated nic info to the VMX. Take care of failed transmissions or
+ * unknown guest information types. Use a fixed sequence of fallback paths
+ * to retry.
+ *
+ * @param[in] ctx Application context.
+ * @param[in] info NicInfoV3 container.
+ *
+ * @retval TRUE Update sent successfully.
+ * @retval FALSE Had trouble with serialization or transmission.
+ *
+ ******************************************************************************
+ */
+
+static Bool
+GuestInfoSendNicInfo(ToolsAppCtx *ctx, // IN
+ NicInfoV3 *info) // IN
+{
+ Bool status = FALSE;
+ GuestNicProto message = {0};
+ NicInfoV3 *info64 = NULL;
+
+ do {
+ switch (gInfoCache.method) {
+ case NIC_INFO_V3_WITH_INFO_IPADDRESS_V3:
+ message.ver = NIC_INFO_V3;
+ message.GuestNicProto_u.nicInfoV3 = info;
+ if (GuestInfoSendNicInfoXdr(ctx, &message, INFO_IPADDRESS_V3)) {
+ status = TRUE;
+ }
+ break;
+ case NIC_INFO_V3_WITH_INFO_IPADDRESS_V2:
+ info64 = GuestNicInfoV3ToV3_64(info);
+ message.ver = NIC_INFO_V3;
+ message.GuestNicProto_u.nicInfoV3 = info64;
+ if (GuestInfoSendNicInfoXdr(ctx, &message, INFO_IPADDRESS_V2)) {
+ status = TRUE;
+ }
+ break;
+ case NIC_INFO_V2_WITH_INFO_IPADDRESS_V2:
+ if (!info64) {
+ info64 = GuestNicInfoV3ToV3_64(info);
+ }
+ {
+ GuestNicList *nicList = NicInfoV3ToV2(info64);
+ message.ver = NIC_INFO_V2;
+ message.GuestNicProto_u.nicsV2 = nicList;
+ if (GuestInfoSendNicInfoXdr(ctx, &message, INFO_IPADDRESS_V2)) {
+ status = TRUE;
+ }
+ VMX_XDR_FREE(xdr_GuestNicList, nicList);
+ free(nicList);
+ }
+ break;
+ case NIC_INFO_V1_WITH_INFO_IPADDRESS:
+ {
+ GuestNicInfoV1 infoV1;
+ GuestInfoConvertNicInfoToNicInfoV1(info, &infoV1);
+ if (GuestInfoSendData(ctx, &infoV1, sizeof(infoV1),
+ INFO_IPADDRESS)) {
+ status = TRUE;
+ }
+ }
+ break;
+ default:
+ g_error("Invalid nicInfo send method: %d\n", gInfoCache.method);
+ break;
+ }
+ } while (!status && (++gInfoCache.method < NIC_INFO_METHOD_MAX));
+
+ if (info64) {
+ g_free(info64->nics.nics_val);
+ g_free(info64);
+ }
+
+ if (status) {
+ g_debug("Updating nicInfo successfully: method=%d\n", gInfoCache.method);
+ } else {
+ gInfoCache.method = NIC_INFO_V3_WITH_INFO_IPADDRESS_V3;
+ g_warning("Fail to send nicInfo: method=%d status=%d\n",
+ gInfoCache.method, status);
+ }
+
+ return status;
+}
+
+
+/*
+ ******************************************************************************
* GuestInfoUpdateVmdb -- */ /**
*
* Push singular GuestInfo snippets to the VMX.
@@ -442,10 +832,11 @@ GuestInfoConvertNicInfoToNicInfoV1(NicInfoV3 *info,
******************************************************************************
*/
-Bool
+static Bool
GuestInfoUpdateVmdb(ToolsAppCtx *ctx, // IN: Application context
GuestInfoType infoType, // IN: guest information type
- void *info) // IN: type specific information
+ void *info, // IN: type specific information
+ size_t infoSize) // IN: size of *info
{
ASSERT(info);
g_debug("Entered update vmdb: %d.\n", infoType);
@@ -485,166 +876,21 @@ GuestInfoUpdateVmdb(ToolsAppCtx *ctx, // IN: Application context
case INFO_IPADDRESS:
{
- static NicInfoVersion supportedVersion = NIC_INFO_V3;
- NicInfoV3 *nicInfoV3 = (NicInfoV3 *)info;
- char *reply = NULL;
- size_t replyLen;
- Bool status;
-
-nicinfo_fsm:
- switch (supportedVersion) {
- case NIC_INFO_V3:
- case NIC_INFO_V2:
- {
- /*
- * 13 = max size of string representation of an int + 3 spaces.
- * XXX Ditch the magic numbers.
- */
- char request[sizeof GUEST_INFO_COMMAND + 13];
- GuestNicProto message = {0};
- GuestNicList *nicList = NULL;
- NicInfoVersion fallbackVersion;
- XDR xdrs;
-
- if (DynXdr_Create(&xdrs) == NULL) {
- return FALSE;
- }
-
- /* Add the RPC preamble: message name, and type. */
- Str_Sprintf(request, sizeof request, "%s %d ",
- GUEST_INFO_COMMAND, INFO_IPADDRESS_V2);
-
- /*
- * Fill in message according to the version we'll attempt. Also
- * note which version we'll fall back to should the VMX reject
- * our update.
- */
- if (supportedVersion == NIC_INFO_V3) {
- message.ver = NIC_INFO_V3;
- message.GuestNicProto_u.nicInfoV3 = nicInfoV3;
-
- fallbackVersion = NIC_INFO_V2;
- } else {
- nicList = NicInfoV3ToV2(nicInfoV3);
- message.ver = NIC_INFO_V2;
- message.GuestNicProto_u.nicsV2 = nicList;
-
- fallbackVersion = NIC_INFO_V1;
- }
-
- /* Write preamble and serialized nic info to XDR stream. */
- if (!DynXdr_AppendRaw(&xdrs, request, strlen(request)) ||
- !xdr_GuestNicProto(&xdrs, &message)) {
- g_warning("Error serializing nic info v%d data.", message.ver);
- DynXdr_Destroy(&xdrs, TRUE);
- return FALSE;
- }
-
- status = RpcChannel_Send(ctx->rpc,
- DynXdr_Get(&xdrs),
- xdr_getpos(&xdrs),
- &reply,
- &replyLen);
- DynXdr_Destroy(&xdrs, TRUE);
-
- /*
- * Do not free/destroy contents of `message`. The v3 nicInfo
- * passed to us belongs to our caller. Instead, we'll only
- * destroy our local V2 converted data.
- */
- if (nicList) {
- VMX_XDR_FREE(xdr_GuestNicList, nicList);
- free(nicList);
- nicList = NULL;
- }
-
- if (!status) {
- g_warning("NicInfo update failed: version %u, reply \"%s\".\n",
- supportedVersion, reply);
- supportedVersion = fallbackVersion;
- vm_free(reply);
- reply = NULL;
- goto nicinfo_fsm;
- }
- }
- break;
-
- case NIC_INFO_V1:
- {
- /*
- * Could be that we are talking to the old protocol that
- * GuestNicInfo is still fixed size. Another try to send the
- * fixed sized Nic info.
- */
- char request[sizeof (GuestNicInfoV1) + sizeof GUEST_INFO_COMMAND +
- 2 + /* 2 bytes are for digits of infotype. */
- 3 * sizeof (char)]; /* 3 spaces */
- GuestNicInfoV1 nicInfo;
-
- Str_Sprintf(request,
- sizeof request,
- "%s %d ",
- GUEST_INFO_COMMAND,
- INFO_IPADDRESS);
-
- GuestInfoConvertNicInfoToNicInfoV1(nicInfoV3, &nicInfo);
-
- memcpy(request + strlen(request),
- &nicInfo,
- sizeof(GuestNicInfoV1));
-
- g_debug("Sending nic info message.\n");
- /* Send all the information in the message. */
- status = RpcChannel_Send(ctx->rpc,
- request,
- sizeof request,
- &reply,
- &replyLen);
-
- g_debug("Just sent fixed sized nic info message.\n");
-
- if (!status) {
- g_debug("Failed to update fixed sized nic information\n");
- vm_free(reply);
- return FALSE;
- }
- }
- break;
- default:
- NOT_REACHED();
+ if (!GuestInfoSendNicInfo(ctx, (NicInfoV3 *) info)) {
+ g_warning("Failed to update nic information.\n");
+ return FALSE;
}
-
- g_debug("Updated new NIC information\n");
- vm_free(reply);
- reply = NULL;
+ break;
}
- break;
case INFO_MEMORY:
- {
- char request[sizeof(GuestMemInfo) + sizeof GUEST_INFO_COMMAND +
- 2 + /* 2 bytes are for digits of infotype. */
- 3 * sizeof (char)]; /* 3 spaces */
- Bool status;
-
- g_debug("Sending GuestMemInfo message.\n");
- Str_Sprintf(request,
- sizeof request,
- "%s %d ",
- GUEST_INFO_COMMAND,
- INFO_MEMORY);
- memcpy(request + strlen(request),
- info, sizeof(GuestMemInfo));
-
- /* Send all the information in the message. */
- status = RpcChannel_Send(ctx->rpc, request, sizeof(request), NULL, NULL);
- if (!status) {
- g_warning("Error sending GuestMemInfo.\n");
- return FALSE;
+ {
+ if (!GuestInfoSendMemoryInfo(ctx, infoSize, info)) {
+ g_warning("Unable to send GuestMemInfo\n");
+ return FALSE;
+ }
+ break;
}
- g_debug("GuestMemInfo sent successfully.\n");
- break;
- }
case INFO_DISK_FREE_SPACE:
{
@@ -652,7 +898,8 @@ nicinfo_fsm:
* 2 accounts for the digits of infotype and 3 for the three
* spaces.
*/
- unsigned int requestSize = sizeof GUEST_INFO_COMMAND + 2 + 3 * sizeof (char);
+ unsigned int requestSize = sizeof GUEST_INFO_COMMAND + 2 +
+ 3 * sizeof (char);
uint8 partitionCount;
size_t offset;
char *request;
@@ -708,7 +955,8 @@ nicinfo_fsm:
}
g_debug("sizeof request is %d\n", requestSize);
- status = RpcChannel_Send(ctx->rpc, request, requestSize, &reply, &replyLen);
+ status = RpcChannel_Send(ctx->rpc, request, requestSize, &reply,
+ &replyLen);
if (status) {
status = (*reply == '\0');
}
@@ -730,7 +978,7 @@ nicinfo_fsm:
break;
}
- g_debug("Returning after updating guest information\n");
+ g_debug("Returning after updating guest information: %d\n", infoType);
return TRUE;
}
@@ -751,7 +999,7 @@ SendUptime(ToolsAppCtx *ctx)
{
gchar *uptime = g_strdup_printf("%"FMT64"u", System_Uptime());
g_debug("Setting guest uptime to '%s'\n", uptime);
- GuestInfoUpdateVmdb(ctx, INFO_UPTIME, uptime);
+ GuestInfoUpdateVmdb(ctx, INFO_UPTIME, uptime, 0);
g_free(uptime);
}
@@ -938,6 +1186,8 @@ GuestInfoClearCache(void)
GuestInfo_FreeNicInfo(gInfoCache.nicInfo);
gInfoCache.nicInfo = NULL;
+
+ gInfoCache.method = NIC_INFO_V3_WITH_INFO_IPADDRESS_V3;
}
@@ -1004,44 +1254,56 @@ NicInfoV3ToV2(const NicInfoV3 *infoV3)
******************************************************************************
* TweakGatherLoop -- */ /**
*
- * @brief Start, stop, reconfigure the GuestInfoGather poll loop.
+ * @brief Start, stop, reconfigure a GuestInfoGather poll loop.
*
- * This function is responsible for creating, manipulating, and resetting the
+ * This function is responsible for creating, manipulating, and resetting a
* GuestInfoGather loop timeout source.
*
- * @param[in] ctx The app context.
- * @param[in] enable Whether to enable the gather loop.
- *
- * @sa CONFNAME_GUESTINFO_POLLINTERVAL
+ * @param[in] ctx The app context.
+ * @param[in] enable Whether to enable the gather loop.
+ * @param[in] cfgKey Config key to fetch user pref.
+ * @param[in] defInterval Default interval value in seconds.
+ * @param[in] callback Function to be called on expiry of interval.
+ * @param[in,out] currInterval Current interval value in seconds.
+ * @param[out] timeoutSource GSource object created.
*
******************************************************************************
*/
static void
TweakGatherLoop(ToolsAppCtx *ctx,
- gboolean enable)
+ gboolean enable,
+ gchar *cfgKey,
+ gint defInterval,
+ GSourceFunc callback,
+ gint *currInterval,
+ GSource **timeoutSource)
{
- GError *gError = NULL;
gint pollInterval = 0;
if (enable) {
- pollInterval = GUESTINFO_TIME_INTERVAL_MSEC;
+ pollInterval = defInterval * 1000;
/*
- * Check the config registry for a custom poll interval, converting from
- * seconds to milliseconds.
+ * Check the config registry for custom poll interval,
+ * converting from seconds to milliseconds.
*/
if (g_key_file_has_key(ctx->config, CONFGROUPNAME_GUESTINFO,
- CONFNAME_GUESTINFO_POLLINTERVAL, NULL)) {
- pollInterval = g_key_file_get_integer(ctx->config, CONFGROUPNAME_GUESTINFO,
- CONFNAME_GUESTINFO_POLLINTERVAL, &gError);
+ cfgKey, NULL)) {
+ GError *gError = NULL;
+
+ pollInterval = g_key_file_get_integer(ctx->config,
+ CONFGROUPNAME_GUESTINFO,
+ cfgKey, &gError);
pollInterval *= 1000;
if (pollInterval < 0 || gError) {
- g_warning("Invalid %s.%s value. Using default.\n",
- CONFGROUPNAME_GUESTINFO, CONFNAME_GUESTINFO_POLLINTERVAL);
- pollInterval = GUESTINFO_TIME_INTERVAL_MSEC;
+ g_warning("Invalid %s.%s value. Using default %us.\n",
+ CONFGROUPNAME_GUESTINFO, cfgKey, defInterval);
+ pollInterval = defInterval * 1000;
}
+
+ g_clear_error(&gError);
}
}
@@ -1049,8 +1311,8 @@ TweakGatherLoop(ToolsAppCtx *ctx,
* If the interval hasn't changed, let's not interfere with the existing
* timeout source.
*/
- if (guestInfoPollInterval == pollInterval) {
- ASSERT(pollInterval || gatherTimeoutSource == NULL);
+ if (pollInterval == *currInterval) {
+ ASSERT(pollInterval || *timeoutSource == NULL);
return;
}
@@ -1059,24 +1321,85 @@ TweakGatherLoop(ToolsAppCtx *ctx,
* exists, then create and attach a new one.
*/
- if (gatherTimeoutSource != NULL) {
- g_source_destroy(gatherTimeoutSource);
- gatherTimeoutSource = NULL;
+ if (*timeoutSource != NULL) {
+ g_source_destroy(*timeoutSource);
+ *timeoutSource = NULL;
+ }
+
+ *currInterval = pollInterval;
+
+ if (*currInterval) {
+ g_info("New value for %s is %us.\n", cfgKey, *currInterval / 1000);
+
+ *timeoutSource = g_timeout_source_new(*currInterval);
+ VMTOOLSAPP_ATTACH_SOURCE(ctx, *timeoutSource, callback, ctx, NULL);
+ g_source_unref(*timeoutSource);
+ } else {
+ g_info("Poll loop for %s disabled.\n", cfgKey);
}
+}
- guestInfoPollInterval = pollInterval;
- if (guestInfoPollInterval) {
- g_info("New poll interval is %us.\n", guestInfoPollInterval / 1000);
+/*
+ ******************************************************************************
+ * TweakGatherLoops -- */ /**
+ *
+ * @brief Start, stop, reconfigure the GuestInfoGather loops.
+ *
+ * This function is responsible for creating, manipulating, and resetting
+ * the GuestInfoGather loops (info and stats) timeout sources.
+ *
+ * @param[in] ctx The app context.
+ * @param[in] enable Whether to enable the gather loops.
+ *
+ * @sa CONFNAME_GUESTINFO_POLLINTERVAL
+ * @sa CONFNAME_GUESTINFO_STATSINTERVAL
+ *
+ ******************************************************************************
+ */
+
+static void
+TweakGatherLoops(ToolsAppCtx *ctx,
+ gboolean enable)
+{
+ gboolean perfmonEnabled;
- gatherTimeoutSource = g_timeout_source_new(guestInfoPollInterval);
- VMTOOLSAPP_ATTACH_SOURCE(ctx, gatherTimeoutSource, GuestInfoGather, ctx, NULL);
- g_source_unref(gatherTimeoutSource);
+ perfmonEnabled = !g_key_file_get_boolean(ctx->config,
+ CONFGROUPNAME_GUESTINFO,
+ CONFNAME_GUESTINFO_DISABLEPERFMON,
+ NULL);
+
+ if (perfmonEnabled) {
+ /*
+ * Tweak GuestStats gather loop
+ */
+ TweakGatherLoop(ctx, enable,
+ CONFNAME_GUESTINFO_STATSINTERVAL,
+ GUESTINFO_STATS_INTERVAL,
+ GuestInfoStatsGather,
+ &guestInfoStatsInterval,
+ &gatherStatsTimeoutSource);
} else {
- g_info("Poll loop disabled.\n");
+ /*
+ * Destroy the existing timeout source, if it exists.
+ */
+ if (gatherStatsTimeoutSource != NULL) {
+ g_source_destroy(gatherStatsTimeoutSource);
+ gatherStatsTimeoutSource = NULL;
+
+ g_info("PerfMon gather loop disabled.\n");
+ }
}
- g_clear_error(&gError);
+ /*
+ * Tweak GuestInfo gather loop
+ */
+ TweakGatherLoop(ctx, enable,
+ CONFNAME_GUESTINFO_POLLINTERVAL,
+ GUESTINFO_POLL_INTERVAL,
+ GuestInfoGather,
+ &guestInfoPollInterval,
+ &gatherInfoTimeoutSource);
}
@@ -1104,7 +1427,7 @@ GuestInfoServerConfReload(gpointer src,
ToolsAppCtx *ctx,
gpointer data)
{
- TweakGatherLoop(ctx, TRUE);
+ TweakGatherLoops(ctx, TRUE);
}
@@ -1129,7 +1452,7 @@ GuestInfoServerIOFreeze(gpointer src,
gboolean freeze,
gpointer data)
{
- TweakGatherLoop(ctx, !freeze);
+ TweakGatherLoops(ctx, !freeze);
}
@@ -1153,12 +1476,18 @@ GuestInfoServerShutdown(gpointer src,
{
GuestInfoClearCache();
- if (gatherTimeoutSource != NULL) {
- g_source_destroy(gatherTimeoutSource);
- gatherTimeoutSource = NULL;
+ if (gatherInfoTimeoutSource != NULL) {
+ g_source_destroy(gatherInfoTimeoutSource);
+ gatherInfoTimeoutSource = NULL;
+ }
+
+ if (gatherStatsTimeoutSource != NULL) {
+ g_source_destroy(gatherStatsTimeoutSource);
+ gatherStatsTimeoutSource = NULL;
}
#ifdef _WIN32
+ GuestInfo_StatProviderShutdown();
NetUtil_FreeIpHlpApiDll();
#endif
}
@@ -1320,17 +1649,20 @@ ToolsOnLoad(ToolsAppCtx *ctx)
g_warning("Failed to load iphlpapi.dll. Cannot report networking details.\n");
return NULL;
}
+
+ ToolsCore_InitializeCOM(ctx);
#endif
regData.regs = VMTools_WrapArray(regs, sizeof *regs, ARRAYSIZE(regs));
memset(&gInfoCache, 0, sizeof gInfoCache);
vmResumed = FALSE;
+ gInfoCache.method = NIC_INFO_V3_WITH_INFO_IPADDRESS_V3;
/*
- * Set up the GuestInfoGather loop.
+ * Set up the GuestInfo gather loops.
*/
- TweakGatherLoop(ctx, TRUE);
+ TweakGatherLoops(ctx, TRUE);
return &regData;
}
diff --git a/open-vm-tools/services/plugins/guestInfo/perfMonLinux.c b/open-vm-tools/services/plugins/guestInfo/perfMonLinux.c
index 4275b799..9946d420 100644
--- a/open-vm-tools/services/plugins/guestInfo/perfMonLinux.c
+++ b/open-vm-tools/services/plugins/guestInfo/perfMonLinux.c
@@ -16,11 +16,6 @@
*
*********************************************************/
-/*
- * This file gathers the virtual memory stats from Linux guest to be
- * passed on to the vmx.
- */
-
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
@@ -28,31 +23,107 @@
#include <sys/wait.h>
#include <string.h>
+#include "vm_basic_defs.h"
#include "vmware.h"
-#include "guestInfo.h"
#include "strutil.h"
#include "debug.h"
+#include "guestInfoInt.h"
+#include "guestStats.h"
+#include "posix.h"
+#include "hashTable.h"
+
+#define GUEST_INFO_PREALLOC_SIZE 4096
+#define INT_AS_HASHKEY(x) ((const void *)(uintptr_t)(x))
-#ifndef NO_PROCPS
-#include "vm_procps.h"
-static void GuestInfoMonitorGetStat(GuestMemInfo *vmStats);
-static Bool GuestInfoMonitorReadMeminfo(GuestMemInfo *vmStats);
-#endif
+#define STAT_FILE "/proc/stat"
+#define VMSTAT_FILE "/proc/vmstat"
+#define UPTIME_FILE "/proc/uptime"
+#define MEMINFO_FILE "/proc/meminfo"
+#define ZONEINFO_FILE "/proc/zoneinfo"
+#define SWAPPINESS_FILE "/proc/sys/vm/swappiness"
+
+
+/*
+ * For now, all data collection is of uint64 values. Rates are always returned
+ * as a double, derived from the uint64 data.
+ *
+ * TODO: Deal with collected and reported data types being different.
+ */
+
+#define DECLARE_STAT(collect, publish, file, isRegExp, locatorString, reportID, units, dataType) \
+ { file, collect, publish, isRegExp, locatorString, reportID, units, dataType }
+
+typedef struct {
+ const char *sourceFile;
+ Bool collect;
+ Bool publish;
+ Bool isRegExp;
+ const char *locatorString;
+ GuestStatToolsID reportID;
+ GuestValueUnits units;
+ GuestValueType dataType;
+} GuestInfoQuery;
+
+GuestInfoQuery guestInfoQuerySpecTable[] = {
+ DECLARE_STAT(TRUE, TRUE, MEMINFO_FILE, FALSE, "Hugepagesize", GuestStatID_HugePageSize, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, TRUE, ZONEINFO_FILE,TRUE, "present", GuestStatID_MemPhysUsable, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, TRUE, MEMINFO_FILE, FALSE, "MemFree", GuestStatID_MemFree, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, TRUE, MEMINFO_FILE, FALSE, "Active(file)", GuestStatID_MemActiveFileCache, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, TRUE, MEMINFO_FILE, FALSE, "SwapFree", GuestStatID_SwapSpaceRemaining, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, TRUE, MEMINFO_FILE, FALSE, "HugePages_Total", GuestStatID_Linux_HugePagesTotal, GuestUnitsHugePages, GuestTypeUint64),
+ DECLARE_STAT(TRUE, TRUE, VMSTAT_FILE, FALSE, "pgpgin", GuestStatID_PageInRate, GuestUnitsPagesPerSecond, GuestTypeDouble),
+ DECLARE_STAT(TRUE, TRUE, VMSTAT_FILE, FALSE, "pgpgout", GuestStatID_PageOutRate, GuestUnitsPagesPerSecond, GuestTypeDouble),
+ DECLARE_STAT(TRUE, TRUE, STAT_FILE, FALSE, "ctxt", GuestStatID_ContextSwapRate, GuestUnitsNumberPerSecond, GuestTypeDouble),
+ DECLARE_STAT(TRUE, TRUE, NULL, FALSE, NULL, GuestStatID_PhysicalPageSize, GuestUnitsBytes, GuestTypeUint64),
+
+ DECLARE_STAT(TRUE, FALSE, MEMINFO_FILE, FALSE, "MemAvailable", GuestStatID_Linux_MemAvailable, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, FALSE, MEMINFO_FILE, FALSE, "Inactive(file)", GuestStatID_Linux_MemInactiveFile, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, FALSE, MEMINFO_FILE, FALSE, "SReclaimable", GuestStatID_Linux_MemSlabReclaim, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, FALSE, MEMINFO_FILE, FALSE, "Buffers", GuestStatID_Linux_MemBuffers, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, FALSE, MEMINFO_FILE, FALSE, "Cached", GuestStatID_Linux_MemCached, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, FALSE, NULL, FALSE, NULL, GuestStatID_SwapSpaceUsed, GuestUnitsKiB, GuestTypeUint64),
+
+ DECLARE_STAT(TRUE, FALSE, MEMINFO_FILE, FALSE, "MemTotal", GuestStatID_Linux_MemTotal, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, FALSE, MEMINFO_FILE, FALSE, "SwapTotal", GuestStatID_SwapFilesCurrent, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, FALSE, NULL, FALSE, NULL, GuestStatID_SwapFilesMax, GuestUnitsKiB, GuestTypeUint64),
+ DECLARE_STAT(TRUE, FALSE, ZONEINFO_FILE, TRUE, "low", GuestStatID_Linux_LowWaterMark, GuestUnitsPages, GuestTypeUint64),
+};
+
+#define N_QUERIES (sizeof guestInfoQuerySpecTable / sizeof(GuestInfoQuery))
+
+typedef struct {
+ int err; // An errno value
+ uint32 count; // Number of instances found
+ uint64 value;
+ GuestInfoQuery *query;
+} GuestInfoStat;
+
+typedef struct {
+ HashTable *exactMatches;
+
+ uint32 numRegExps;
+ GuestInfoStat **regExps;
+
+ uint32 numStats;
+ GuestInfoStat *stats;
+
+ HashTable *reportMap;
+
+ Bool timeData;
+ double timeStamp;
+} GuestInfoCollector;
-#define LINUX_MEMINFO_FLAGS (MEMINFO_MEMTOTAL | MEMINFO_MEMFREE | MEMINFO_MEMBUFF |\
- MEMINFO_MEMCACHE | MEMINFO_MEMACTIVE | MEMINFO_MEMINACTIVE |\
- MEMINFO_SWAPINRATE | MEMINFO_SWAPOUTRATE |\
- MEMINFO_IOINRATE | MEMINFO_IOOUTRATE)
/*
*----------------------------------------------------------------------
*
- * GuestInfo_PerfMon --
+ * GuestInfoGetUpTime --
*
- * Gather performance stats.
+ * What time is it?
*
* Results:
- * Gathered stats. Returns FALSE on failure.
+ * TRUE Success! *now is populated
+ * FALSE Failure! *now remains unchanged
*
* Side effects:
* None.
@@ -60,32 +131,98 @@ static Bool GuestInfoMonitorReadMeminfo(GuestMemInfo *vmStats);
*----------------------------------------------------------------------
*/
-Bool
-GuestInfo_PerfMon(GuestMemInfo *vmStats) // OUT: filled vmstats
+static Bool
+GuestInfoGetUpTime(double *now) // OUT:
{
-#ifndef NO_PROCPS
- ASSERT(vmStats);
- vmStats->flags = 0;
- GuestInfoMonitorGetStat(vmStats);
- if (GuestInfoMonitorReadMeminfo(vmStats)) {
- vmStats->flags |= LINUX_MEMINFO_FLAGS;
- return TRUE;
+ char line[512];
+ Bool result = FALSE;
+ FILE *fp = Posix_Fopen(UPTIME_FILE, "r");
+
+ if (fp == NULL) {
+ return result;
+ }
+
+ if (fgets(line, sizeof line, fp) != NULL) {
+ double idle;
+
+ if (sscanf(line, "%lf %lf", now, &idle) == 2) {
+ result = TRUE;
+ }
}
-#endif
- return FALSE;
+
+ fclose(fp);
+
+ return result;
}
-#ifndef NO_PROCPS
/*
*----------------------------------------------------------------------
*
- * GuestInfoMonitorGetStat --
+ * GuestInfoStoreStat --
*
- * Calls getstat() to gather memory stats.
+ * Store a stat.
*
* Results:
- * Gathered stats in vmStats.
+ * None.
+ *
+ * Side effects:
+ * Handles overflow detection.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GuestInfoStoreStat(const char *pathName, // IN: file stat is in
+ GuestInfoStat *stat, // IN/OUT: stat
+ uint64 value) // IN: value to be added to stat
+{
+ ASSERT(stat);
+ ASSERT(stat->query);
+
+ // TODO: consider supporting regexp here.
+ if (strcmp(stat->query->sourceFile, pathName) == 0) {
+ switch (stat->err) {
+ case 0:
+ ASSERT(stat->count != 0);
+
+ if (((stat->count + 1) < stat->count) ||
+ ((stat->value + value) < stat->value)) {
+ stat->err = EOVERFLOW;
+ } else {
+ stat->count++;
+ stat->value += value;
+ }
+ break;
+
+ case ENOENT:
+ ASSERT(stat->count == 0);
+
+ stat->err = 0;
+ stat->count = 1;
+ stat->value = value;
+ break;
+
+ default: // Some sort of error - sorry, thank you for playing...
+ break;
+ }
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoCollectStat --
+ *
+ * Collect a stat.
+ *
+ * NOTE: Exact match data cannot be used in a regExp. This is a
+ * performance choice. We can discuss this when we have full
+ * programmability.
+ *
+ * Results:
+ * None.
*
* Side effects:
* None.
@@ -94,59 +231,41 @@ GuestInfo_PerfMon(GuestMemInfo *vmStats) // OUT: filled vmstats
*/
static void
-GuestInfoMonitorGetStat(GuestMemInfo *vmStats) // OUT: filled vmstats
+GuestInfoCollectStat(const char *pathName, // IN:
+ GuestInfoCollector *collector, // IN/OUT:
+ const char *fieldName, // IN:
+ uint64 value) // IN:
{
- uint32 hz = Hertz;
- uint32 dummy;
- jiff cpuUse[2];
- jiff cpuNic[2];
- jiff cpuSys[2];
- jiff cpuIdl[2];
- jiff cpuIow[2];
- jiff cpuXxx[2];
- jiff cpuYyy[2];
- jiff cpuZzz[2];
- jiff cpuTotal;
- jiff cpuHalf;
- unsigned long pageIn[2];
- unsigned long pageOut[2];
- unsigned long swapIn[2];
- unsigned long swapOut[2];
- unsigned int dummy2[2];
- unsigned long kb_per_page = sysconf(_SC_PAGESIZE) / 1024ul;
+ GuestInfoStat *stat = NULL;
- meminfo();
- getstat(cpuUse, cpuNic, cpuSys, cpuIdl, cpuIow, cpuXxx, cpuYyy, cpuZzz,
- pageIn, pageOut, swapIn, swapOut, dummy2, dummy2, &dummy, &dummy,
- &dummy, &dummy);
+ if (!HashTable_Lookup(collector->exactMatches, fieldName, (void **) &stat)) {
+ uint32 i;
- cpuTotal = *cpuUse + *cpuNic + *cpuSys + *cpuXxx +
- *cpuYyy + *cpuIdl + *cpuIow + *cpuZzz;
- cpuHalf = cpuTotal / 2UL;
+ for (i = 0; i < collector->numRegExps; i++) {
+ GuestInfoStat *thisOne = collector->regExps[i];
- vmStats->memFree = kb_main_free;
- vmStats->memBuff = kb_main_buffers;
- vmStats->memCache = kb_main_cached,
- vmStats->memInactive = kb_inactive;
- vmStats->memActive = kb_active;
+ if (StrUtil_StartsWith(fieldName, thisOne->query->locatorString)) {
+ stat = thisOne;
+ }
+ }
+ }
- vmStats->swapInRate = (uint64)((*swapIn * kb_per_page * hz + cpuHalf) / cpuTotal);
- vmStats->swapOutRate = (uint64)((*swapOut * kb_per_page * hz + cpuHalf) / cpuTotal);
- vmStats->ioInRate = (uint64)((*pageIn * kb_per_page * hz + cpuHalf) / cpuTotal);
- vmStats->ioOutRate = (uint64)((*pageOut * kb_per_page * hz + cpuHalf) / cpuTotal);
+ if (stat != NULL) {
+ GuestInfoStoreStat(pathName, stat, value);
+ }
}
/*
*----------------------------------------------------------------------
*
- * GuestInfoMonitorReadMeminfo --
+ * GuestInfoReadProcMemInfoData --
*
- * Reads /proc/meminfo to gather phsycial memory and huge page stats.
+ * Reads /proc/meminfo to contribute to a collection.
*
* Results:
- * Read /proc/meminfo for total physical memory and huge pages info.
- * Returns FALSE on failure.
+ * TRUE Success!
+ * FALSE Failure!
*
* Side effects:
* None.
@@ -155,36 +274,897 @@ GuestInfoMonitorGetStat(GuestMemInfo *vmStats) // OUT: filled vmstats
*/
static Bool
-GuestInfoMonitorReadMeminfo(GuestMemInfo *vmStats) // OUT: filled vmstats
+GuestInfoProcMemInfoData(GuestInfoCollector *collector) // IN:
{
- char buf[512];
- uint64 value;
- FILE *fp;
+ char line[512];
+ FILE *fp = Posix_Fopen(MEMINFO_FILE, "r");
- /* Get the total memory, and huge page info from /proc/meminfo. */
- fp = fopen("/proc/meminfo", "r");
- if (!fp) {
- Log("GuestInfoMonitorReadMeminfo: Error opening /proc/meminfo.\n");
+ if (fp == NULL) {
+ g_warning("%s: Error opening " MEMINFO_FILE ".\n", __FUNCTION__);
return FALSE;
}
- while(!feof(fp)) {
- if (fscanf(fp, "%s %"FMT64"u", buf, &value) != 2) {
+ while (fgets(line, sizeof line, fp) == line) {
+ char *p;
+ uint64 value = 0;
+ char *fieldName = strtok(line, " \t");
+ char *fieldData = strtok(NULL, " \t");
+
+ if (fieldName == NULL) {
continue;
}
- if (StrUtil_StartsWith(buf, "MemTotal")) {
- vmStats->memTotal = value;
+
+ p = strrchr(fieldName, ':');
+ if (p == NULL) {
+ continue;
+ } else {
+ *p = '\0';
}
- if (StrUtil_StartsWith(buf, "HugePages_Total")) {
- vmStats->hugePagesTotal = value;
- vmStats->flags |= MEMINFO_HUGEPAGESTOTAL;
+
+ if ((fieldData == NULL) ||
+ (sscanf(fieldData, "%"FMT64"u", &value) != 1)) {
+ continue;
}
- if (StrUtil_StartsWith(buf, "HugePages_Free")) {
- vmStats->hugePagesFree = value;
- vmStats->flags |= MEMINFO_HUGEPAGESFREE;
+
+ GuestInfoCollectStat(MEMINFO_FILE, collector, fieldName, value);
+ }
+
+ fclose(fp);
+
+ return TRUE;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoProcData --
+ *
+ * Reads a "stat file" and contribute to the collection.
+ *
+ * Results:
+ * TRUE Success!
+ * FALSE Failure!
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+GuestInfoProcData(const char *pathName, // IN: path name
+ GuestInfoCollector *collector) // IN:
+{
+ char line[4096];
+ FILE *fp = Posix_Fopen(pathName, "r");
+
+ if (fp == NULL) {
+ g_warning("%s: Error opening %s.\n", __FUNCTION__, pathName);
+ return FALSE;
+ }
+
+ while (fgets(line, sizeof line, fp) != NULL) {
+ uint64 value = 0;
+ char *fieldName = strtok(line, " \t");
+ char *fieldData = strtok(NULL, " \t");
+
+ if (fieldName == NULL) {
+ continue;
+ }
+
+ if ((fieldData == NULL) ||
+ (sscanf(fieldData, "%"FMT64"u", &value) != 1)) {
+ continue;
}
+
+ GuestInfoCollectStat(pathName, collector, fieldName, value);
}
+
fclose(fp);
+
+ return TRUE;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoDeriveSwapData --
+ *
+ * Update the swap stats that are calculated rather than fetched.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GuestInfoDeriveSwapData(GuestInfoCollector *collector) // IN: current collection
+{
+ uint64 swapFree = 0;
+ uint64 swapTotal = 0;
+ uint64 swapUsed = 0;
+ GuestInfoStat *swapSpaceRemaining = NULL;
+ GuestInfoStat *swapSpaceUsed = NULL;
+ GuestInfoStat *swapFilesCurrent = NULL;
+ GuestInfoStat *swapFilesMax = NULL;
+
+ HashTable_Lookup(collector->reportMap,
+ INT_AS_HASHKEY(GuestStatID_SwapFilesMax),
+ (void **) &swapFilesMax);
+
+ HashTable_Lookup(collector->reportMap,
+ INT_AS_HASHKEY(GuestStatID_SwapFilesCurrent),
+ (void **) &swapFilesCurrent);
+
+ HashTable_Lookup(collector->reportMap,
+ INT_AS_HASHKEY(GuestStatID_SwapSpaceUsed),
+ (void **) &swapSpaceUsed);
+
+ HashTable_Lookup(collector->reportMap,
+ INT_AS_HASHKEY(GuestStatID_SwapSpaceRemaining),
+ (void **) &swapSpaceRemaining);
+
+ /*
+ * Start by getting SwapTotal (from Id_SwapFilesCurrent).
+ * Set Id_SwapFilesMax to that if it doesn't have its own opinion.
+ */
+ if ((swapFilesCurrent != NULL) && (swapFilesCurrent->err == 0)) {
+ swapTotal = swapFilesCurrent->value;
+
+ if ((swapFilesMax != NULL) && (swapFilesMax->err != 0)) {
+ swapFilesMax->value = swapTotal;
+ swapFilesMax->count = 1;
+ swapFilesMax->err = 0;
+ }
+
+ /*
+ * Get SwapFree (from Id_SwapSpaceRemaining)
+ * Set Id_SwapSpaceUsed to SwapTotal-SwapFree if it doesn't have its
+ * own opinion.
+ */
+ if ((swapSpaceRemaining != NULL) && (swapSpaceRemaining->err == 0)) {
+ swapFree = swapSpaceRemaining->value;
+
+ ASSERT(swapTotal >= swapFree);
+ swapUsed = (swapTotal >= swapFree) ? swapTotal - swapFree : 0;
+
+ if ((swapSpaceUsed != NULL) && (swapSpaceUsed->err != 0)) {
+ swapSpaceUsed->value = swapUsed;
+ swapSpaceUsed->count = 1;
+ swapSpaceUsed->err = 0;
+ }
+ }
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoCollect --
+ *
+ * Fill the specified collector with as much sampled data as possible.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GuestInfoCollect(GuestInfoCollector *collector) // IN:
+{
+ uint32 i;
+ GuestInfoStat *stat;
+ uint64 pageSize = sysconf(_SC_PAGESIZE);
+
+ /* Reset all values */
+ for (i = 0; i < collector->numStats; i++) {
+ GuestInfoStat *stat = &collector->stats[i];
+
+ stat->err = ENOENT; // There is no data here
+ stat->count = 0;
+ stat->value = 0;
+ }
+
+ /* Collect new values */
+ GuestInfoProcMemInfoData(collector);
+ GuestInfoProcData(VMSTAT_FILE, collector);
+ GuestInfoProcData(STAT_FILE, collector);
+ GuestInfoProcData(ZONEINFO_FILE, collector);
+ GuestInfoDeriveSwapData(collector);
+
+ collector->timeData = GuestInfoGetUpTime(&collector->timeStamp);
+
+ /*
+ * We make sure physical page size is always present.
+ */
+
+ stat = NULL;
+ HashTable_Lookup(collector->reportMap,
+ INT_AS_HASHKEY(GuestStatID_PhysicalPageSize),
+ (void **) &stat);
+
+ if ((stat != NULL) && (stat->err != 0)) {
+ stat->value = pageSize;
+ stat->count = 1;
+ stat->err = 0;
+ }
+
+ /*
+ * Attempt to fix up memPhysUsable if it is not available.
+ */
+
+ stat = NULL;
+ HashTable_Lookup(collector->reportMap,
+ INT_AS_HASHKEY(GuestStatID_MemPhysUsable),
+ (void **) &stat);
+
+ ASSERT(stat != NULL); // Must be in table
+
+ if (stat->err == 0) {
+ stat->value *= (pageSize / 1024); // Convert pages to KiB
+ } else {
+ GuestInfoStat *memTotal = NULL;
+
+ HashTable_Lookup(collector->reportMap,
+ INT_AS_HASHKEY(GuestStatID_Linux_MemTotal),
+ (void **) &memTotal);
+
+ if ((memTotal != NULL) && (memTotal->err == 0)) {
+ stat->err = 0;
+ stat->count = 1;
+ stat->value = memTotal->value;
+ }
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoLegacy --
+ *
+ * Fill in the legacy portion of the data to be returned.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GuestInfoLegacy(GuestInfoCollector *current, // IN: current collection
+ GuestMemInfo *legacy) // OUT: data filled out
+{
+ GuestInfoStat *stat;
+
+ memset(legacy, 0, sizeof *legacy);
+
+ legacy->version = GUESTMEMINFO_V5;
+ legacy->flags = 0;
+
+ stat = NULL;
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_MemPhysUsable),
+ (void **) &stat);
+
+ if ((stat != NULL) && (stat->err == 0)) {
+ legacy->memTotal = stat->value;
+ legacy->flags |= MEMINFO_MEMTOTAL;
+ }
+
+ stat = NULL;
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_Linux_HugePagesTotal),
+ (void **) &stat);
+
+ if ((stat != NULL) && (stat->err == 0)) {
+ legacy->hugePagesTotal = stat->value;
+ legacy->flags |= MEMINFO_HUGEPAGESTOTAL;
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoBytesNeededUIntDatum --
+ *
+ * Results:
+ * Returns the number of bytes needed to encode a UInt.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static uint16
+GuestInfoBytesNeededUIntDatum(uint64 value) // IN:
+{
+ if (value == 0) {
+ return 0;
+ } else if (value <= MAX_UINT8) {
+ return sizeof(uint8);
+ } else if (value <= MAX_UINT16) {
+ return sizeof(uint16);
+ } else if (value <= MAX_UINT32) {
+ return sizeof(uint32);
+ } else {
+ return sizeof(uint64);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoAppendStat --
+ *
+ * Append information about the specified stat to the DynBuf of stat
+ * data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory may be dynamically allocated (via DynBuf).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GuestInfoAppendStat(int errnoValue, // IN:
+ Bool emitNameSpace, // IN:
+ GuestStatToolsID reportID, // IN:
+ GuestValueUnits units, // IN:
+ GuestValueType valueType, // IN:
+ void *value, // IN:
+ size_t valueSize, // IN:
+ DynBuf *stats) // IN/OUT:
+{
+ const char *NameSpace = GUEST_TOOLS_NAMESPACE;
+ uint64 value64;
+ GuestStatHeader header;
+ GuestDatumHeader datum;
+
+ header.datumFlags = GUEST_DATUM_ID |
+ GUEST_DATUM_VALUE_TYPE_ENUM |
+ GUEST_DATUM_VALUE_UNIT_ENUM;
+ if (emitNameSpace) {
+ header.datumFlags |= GUEST_DATUM_NAMESPACE;
+ }
+ if (errnoValue == 0) {
+ header.datumFlags |= GUEST_DATUM_VALUE;
+ }
+ DynBuf_Append(stats, &header, sizeof header);
+
+ if (header.datumFlags & GUEST_DATUM_NAMESPACE) {
+ size_t nameSpaceLen = strlen(NameSpace) + 1;
+ datum.dataSize = nameSpaceLen;
+ DynBuf_Append(stats, &datum, sizeof datum);
+ DynBuf_Append(stats, NameSpace, nameSpaceLen);
+ }
+
+ if (header.datumFlags & GUEST_DATUM_ID) {
+ value64 = reportID;
+ datum.dataSize = GuestInfoBytesNeededUIntDatum(value64);
+ DynBuf_Append(stats, &datum, sizeof datum);
+ DynBuf_Append(stats, &value64, datum.dataSize);
+ }
+
+ if (header.datumFlags & GUEST_DATUM_VALUE_TYPE_ENUM) {
+ value64 = valueType;
+ datum.dataSize = GuestInfoBytesNeededUIntDatum(value64);
+ DynBuf_Append(stats, &datum, sizeof datum);
+ DynBuf_Append(stats, &value64, datum.dataSize);
+ }
+
+ if (header.datumFlags & GUEST_DATUM_VALUE_UNIT_ENUM) {
+ value64 = units;
+ datum.dataSize = GuestInfoBytesNeededUIntDatum(value64);
+ DynBuf_Append(stats, &datum, sizeof datum);
+ DynBuf_Append(stats, &value64, datum.dataSize);
+ }
+
+ if (header.datumFlags & GUEST_DATUM_VALUE) {
+ datum.dataSize = valueSize;
+ DynBuf_Append(stats, &datum, sizeof datum);
+ DynBuf_Append(stats, value, valueSize);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoAppendRate --
+ *
+ * Compute a rate and then append it to the stat buffer.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GuestInfoAppendRate(Bool emitNameSpace, // IN:
+ GuestStatToolsID reportID, // IN: Id of the stat
+ GuestInfoCollector *current, // IN: current collection
+ GuestInfoCollector *previous, // IN: previous collection
+ DynBuf *statBuf) // IN/OUT: stat data
+{
+ double valueDouble = 0.0;
+ int errnoValue = ENOENT;
+ GuestInfoStat *currentStat = NULL;
+ GuestInfoStat *previousStat = NULL;
+
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(reportID),
+ (void **) &currentStat);
+
+ HashTable_Lookup(previous->reportMap,
+ INT_AS_HASHKEY(reportID),
+ (void **) &previousStat);
+
+ if (current->timeData &&
+ previous->timeData &&
+ ((currentStat != NULL) && (currentStat->err == 0)) &&
+ ((previousStat != NULL) && (previousStat->err == 0))) {
+ double timeDelta = current->timeStamp - previous->timeStamp;
+ double valueDelta = currentStat->value - previousStat->value;
+
+ valueDouble = valueDelta / timeDelta;
+ errnoValue = 0;
+ }
+
+ if (currentStat != NULL) {
+ float valueFloat;
+ void *valuePointer;
+ size_t valueSize;
+
+ if (valueDouble == 0) {
+ valuePointer = NULL;
+ valueSize = 0;
+ } else {
+ valueFloat = (float)valueDouble;
+ if ((double)valueFloat == valueDouble) {
+ valuePointer = &valueFloat;
+ valueSize = sizeof valueFloat;
+ } else {
+ valuePointer = &valueDouble;
+ valueSize = sizeof valueDouble;
+ }
+ }
+
+ GuestInfoAppendStat(errnoValue, emitNameSpace, reportID,
+ currentStat->query->units, GuestTypeDouble,
+ valuePointer, valueSize, statBuf);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoAppendMemNeeded --
+ *
+ * Synthesize memNeeded and append it to the stat buffer.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GuestInfoAppendMemNeeded(GuestInfoCollector *current, // IN: current collection
+ Bool emitNameSpace, // IN:
+ DynBuf *statBuf) // IN/OUT: stats data
+{
+ uint64 memNeeded;
+ uint64 memNeededReservation;
+ uint64 memAvailable = 0;
+ GuestInfoStat *memAvail = NULL;
+ GuestInfoStat *memPhysUsable = NULL;
+
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_MemPhysUsable),
+ (void **) &memPhysUsable);
+
+ ASSERT(memPhysUsable != NULL);
+
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_Linux_MemAvailable),
+ (void **) &memAvail);
+
+ if ((memAvail != NULL) && (memAvail->err == 0)) {
+ memAvailable = memAvail->value;
+ } else {
+ GuestInfoStat *memFree = NULL;
+ GuestInfoStat *memCache = NULL;
+ GuestInfoStat *memBuffers = NULL;
+ GuestInfoStat *memActiveFile = NULL;
+ GuestInfoStat *memSlabReclaim = NULL;
+ GuestInfoStat *memInactiveFile = NULL;
+ GuestInfoStat *lowWaterMark = NULL;
+
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_MemFree),
+ (void **) &memFree);
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_Linux_MemCached),
+ (void **) &memCache);
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_Linux_MemBuffers),
+ (void **) &memBuffers);
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_MemActiveFileCache),
+ (void **) &memActiveFile);
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_Linux_MemSlabReclaim),
+ (void **) &memSlabReclaim);
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_Linux_MemInactiveFile),
+ (void **) &memInactiveFile);
+ HashTable_Lookup(current->reportMap,
+ INT_AS_HASHKEY(GuestStatID_Linux_LowWaterMark),
+ (void **) &lowWaterMark);
+
+ if (((memFree != NULL) && (memFree->err == 0)) &&
+ ((memCache != NULL) && (memCache->err == 0)) &&
+ ((memBuffers != NULL) && (memBuffers->err == 0)) &&
+ (memActiveFile != NULL) &&
+ (memSlabReclaim != NULL) &&
+ (memInactiveFile != NULL) &&
+ ((lowWaterMark != NULL) && (lowWaterMark->err == 0))) {
+ uint64 pageCache;
+ unsigned long kbPerPage = sysconf(_SC_PAGESIZE) / 1024UL;
+ uint64 lowWaterMarkValue = lowWaterMark->value * kbPerPage;
+
+ memAvailable = memFree->value - lowWaterMarkValue;
+
+ if ((memActiveFile->err == 0) && (memInactiveFile->err == 0)) {
+ pageCache = memActiveFile->value + memInactiveFile->value;
+ } else {
+ /*
+ * If the kernel is too old to expose Active/Inactive file,
+ * this is the best approxmation for pageCache.
+ */
+ pageCache = memCache->value + memBuffers->value;
+ }
+
+ pageCache -= MIN(pageCache / 2, lowWaterMarkValue);
+ memAvailable += pageCache;
+
+ if (memSlabReclaim->err == 0) {
+ memAvailable += memSlabReclaim->value -
+ MIN(memSlabReclaim->value / 2, lowWaterMarkValue);
+ }
+
+ if ((int64)memAvailable < 0) {
+ memAvailable = 0;
+ }
+ }
+ }
+
+ if (memPhysUsable->err == 0) {
+ /*
+ * Reserve 5% of physical RAM for surges.
+ */
+ memNeededReservation = memPhysUsable->value / 20;
+
+ if (memAvailable > memNeededReservation) {
+ memAvailable -= memNeededReservation;
+ } else {
+ memAvailable = 0;
+ }
+
+ /*
+ * We got these values from one read of /proc/meminfo. Everything should
+ * really be coherent.
+ */
+ ASSERT(memPhysUsable->value >= memAvailable);
+ memNeeded = memPhysUsable->value - memAvailable;
+ } else {
+ memNeeded = 0;
+ memNeededReservation = 0;
+ }
+
+ GuestInfoAppendStat(0,
+ emitNameSpace,
+ GuestStatID_MemNeeded,
+ GuestUnitsKiB, GuestTypeUint64,
+ &memNeeded,
+ GuestInfoBytesNeededUIntDatum(memNeeded),
+ statBuf);
+
+ emitNameSpace = FALSE;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoIsRate --
+ *
+ * Is the specified unit a rate?
+ *
+ * Results:
+ * TRUE Yes
+ * FALSE No
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+GuestInfoIsRate(GuestValueUnits units) // IN:
+{
+ return ((units & GuestUnitsModifier_Rate) != 0);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoEncodeStats --
+ *
+ * Encode the guest stats.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GuestInfoEncodeStats(GuestInfoCollector *current, // IN: current collection
+ GuestInfoCollector *previous, // IN: previous collection
+ DynBuf *statBuf) // IN/OUT: stats data
+{
+ uint32 i;
+ GuestMemInfo legacy;
+ Bool emitNameSpace = TRUE;
+
+ /* Provide legacy data for backwards compatibility */
+ GuestInfoLegacy(current, &legacy);
+
+ DynBuf_Append(statBuf, &legacy, sizeof legacy);
+
+ /* Provide data in the new, extensible format. */
+ for (i = 0; i < current->numStats; i++) {
+ GuestInfoStat *stat = &current->stats[i];
+
+ if (!stat->query->publish) {
+ continue;
+ }
+
+ if (GuestInfoIsRate(stat->query->units)) {
+ ASSERT(stat->query->dataType == GuestTypeDouble);
+ GuestInfoAppendRate(emitNameSpace, stat->query->reportID,
+ current, previous, statBuf);
+ } else {
+ ASSERT(stat->query->dataType == GuestTypeUint64);
+ GuestInfoAppendStat(stat->err,
+ emitNameSpace,
+ stat->query->reportID,
+ stat->query->units,
+ stat->query->dataType,
+ &stat->value,
+ GuestInfoBytesNeededUIntDatum(stat->value),
+ statBuf);
+ }
+
+ emitNameSpace = FALSE; // use the smallest representation
+ }
+
+ GuestInfoAppendMemNeeded(current, emitNameSpace, statBuf);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoDestroyCollector --
+ *
+ * Destroy the collector representation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GuestInfoDestroyCollector(GuestInfoCollector *collector) // IN:
+{
+ if (collector != NULL) {
+ HashTable_Free(collector->exactMatches);
+ HashTable_Free(collector->reportMap);
+ free(collector->regExps);
+ free(collector->stats);
+ free(collector);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfoConstructCollector --
+ *
+ * Construct a collector.
+ *
+ * Results:
+ * NULL Failure!
+ * !NULL Success! Collector representation.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static GuestInfoCollector *
+GuestInfoConstructCollector(GuestInfoQuery *queries, // IN:
+ uint32 numQueries) // IN:
+{
+ uint32 i;
+ uint32 regExp = 0;
+ GuestInfoCollector *collector = calloc(1, sizeof *collector);
+
+ if (collector == NULL) {
+ return NULL;
+ }
+
+ collector->reportMap = HashTable_Alloc(256, HASH_INT_KEY, NULL);
+
+ collector->exactMatches = HashTable_Alloc(256,
+ HASH_STRING_KEY | HASH_FLAG_COPYKEY,
+ NULL);
+
+ collector->numRegExps = 0;
+ for (i = 0; i < numQueries; i++) {
+ if (queries[i].isRegExp && queries[i].collect) {
+ collector->numRegExps++;
+ }
+ }
+
+ collector->numStats = numQueries;
+ collector->stats = calloc(numQueries, sizeof *collector->stats);
+ collector->regExps = calloc(collector->numRegExps, sizeof(GuestInfoStat *));
+
+ if ((collector->exactMatches == NULL) ||
+ (collector->reportMap == NULL) ||
+ ((collector->numRegExps != 0) && (collector->regExps == NULL)) ||
+ ((collector->numStats != 0) && (collector->stats == NULL))) {
+ GuestInfoDestroyCollector(collector);
+ return NULL;
+ }
+
+ regExp = 0;
+
+ for (i = 0; i < numQueries; i++) {
+ GuestInfoQuery *query = &queries[i];
+ GuestInfoStat *stat = &collector->stats[i];
+
+ ASSERT(query->reportID);
+
+ stat->query = query;
+
+ if (!query->collect) {
+ continue;
+ }
+
+ if (query->isRegExp) {
+ ASSERT(query->locatorString);
+
+ collector->regExps[regExp++] = stat;
+ } else {
+ if (query->locatorString != NULL) {
+ HashTable_Insert(collector->exactMatches, query->locatorString,
+ stat);
+ }
+ }
+
+ /* The report lookup */
+ HashTable_Insert(collector->reportMap, INT_AS_HASHKEY(query->reportID),
+ stat);
+ }
+
+ return collector;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GuestInfo_PerfMon --
+ *
+ * Gather performance stats.
+ *
+ * Results:
+ * TRUE Success! statBuf contains collected data
+ * FALSE Failure! statBuf contains no collected data
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+GuestInfo_PerfMon(DynBuf *statBuf) // IN/OUT: inited, ready to fill
+{
+ GuestInfoCollector *temp;
+ static GuestInfoCollector *current = NULL;
+ static GuestInfoCollector *previous = NULL;
+
+ ASSERT(statBuf && DynBuf_GetSize(statBuf) == 0);
+
+ /* Preallocate space to minimize realloc operations. */
+ if (!DynBuf_Enlarge(statBuf, GUEST_INFO_PREALLOC_SIZE)) {
+ return FALSE;
+ }
+
+ /* First time through, allocate all necessary memory */
+ if (previous == NULL) {
+ current = GuestInfoConstructCollector(guestInfoQuerySpecTable,
+ N_QUERIES);
+
+ previous = GuestInfoConstructCollector(guestInfoQuerySpecTable,
+ N_QUERIES);
+ }
+
+ if ((current == NULL) ||
+ (previous == NULL)) {
+ GuestInfoDestroyCollector(current);
+ current = NULL;
+ GuestInfoDestroyCollector(previous);
+ previous = NULL;
+ return FALSE;
+ }
+
+ /* Collect the current data */
+ GuestInfoCollect(current);
+
+ /* Encode the captured data */
+ GuestInfoEncodeStats(current, previous, statBuf);
+
+ /* Switch the collections for next time. */
+ temp = current;
+ current = previous;
+ previous = temp;
+
return TRUE;
}
-#endif
+
diff --git a/open-vm-tools/services/plugins/hgfsServer/hgfsPlugin.c b/open-vm-tools/services/plugins/hgfsServer/hgfsPlugin.c
index 7c0540e4..a1918796 100644
--- a/open-vm-tools/services/plugins/hgfsServer/hgfsPlugin.c
+++ b/open-vm-tools/services/plugins/hgfsServer/hgfsPlugin.c
@@ -115,9 +115,9 @@ HgfsServerCapReg(gpointer src,
gchar *msg;
const char *appName = NULL;
- if (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) == 0) {
+ if (TOOLS_IS_MAIN_SERVICE(ctx)) {
appName = TOOLS_DAEMON_NAME;
- } else if (strcmp(ctx->name, VMTOOLS_USER_SERVICE) == 0) {
+ } else if (TOOLS_IS_USER_SERVICE(ctx)) {
appName = TOOLS_DND_NAME;
} else {
NOT_REACHED();
@@ -162,8 +162,7 @@ ToolsOnLoad(ToolsAppCtx *ctx)
};
HgfsServerMgrData *mgrData;
- if (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) != 0 &&
- strcmp(ctx->name, VMTOOLS_USER_SERVICE) != 0) {
+ if (!TOOLS_IS_MAIN_SERVICE(ctx) && !TOOLS_IS_USER_SERVICE(ctx)) {
g_info("Unknown container '%s', not loading HGFS plugin.", ctx->name);
return NULL;
}
diff --git a/open-vm-tools/services/plugins/powerOps/powerOps.c b/open-vm-tools/services/plugins/powerOps/powerOps.c
index 2ec24715..7d46e029 100644
--- a/open-vm-tools/services/plugins/powerOps/powerOps.c
+++ b/open-vm-tools/services/plugins/powerOps/powerOps.c
@@ -38,6 +38,7 @@
# define INVALID_PID NULL
#else
# define INVALID_PID (GPid) -1
+#include <sys/wait.h>
#endif
#if !defined(__APPLE__)
@@ -206,10 +207,10 @@ PowerOpsStateChangeDone(PowerOpState *state,
/* Finally, perform the requested operation. */
if (success) {
if (state->stateChgInProgress == GUESTOS_STATECHANGE_REBOOT) {
- g_debug("Initiating reboot.\n");
+ g_message("Initiating reboot.\n");
System_Shutdown(TRUE);
} else if (state->stateChgInProgress == GUESTOS_STATECHANGE_HALT) {
- g_debug("Initiating halt.\n");
+ g_message("Initiating halt.\n");
System_Shutdown(FALSE);
}
}
@@ -240,7 +241,7 @@ PowerOpsScriptCallback(gpointer _state)
success = (ProcMgr_GetExitCode(state->pid, &exitcode) == 0 &&
exitcode == 0);
- g_debug("Script exit code: %d, success = %d\n", exitcode, success);
+ g_message("Script exit code: %d, success = %d\n", exitcode, success);
PowerOpsStateChangeDone(state, success);
ProcMgr_Free(state->pid);
state->pid = INVALID_PID;
@@ -286,7 +287,7 @@ PowerOpsRunScript(PowerOpState *state,
quoted = g_strdup_printf("\"%s\"", script);
}
- g_debug("Executing script: %s\n", (quoted != NULL) ? quoted : script);
+ g_message("Executing script: %s\n", (quoted != NULL) ? quoted : script);
state->pid = ProcMgr_ExecAsync((quoted != NULL) ? quoted : script, &procArgs);
g_free(quoted);
@@ -308,7 +309,7 @@ PowerOpsRunScript(PowerOpState *state,
* Callback for when the script process finishes on POSIX systems.
*
* @param[in] pid Child pid.
- * @param[in] exitcode Exit status of script.
+ * @param[in] exitStatus Exit status of script.
* @param[in] _state Plugin state.
*
* @return FALSE.
@@ -316,15 +317,26 @@ PowerOpsRunScript(PowerOpState *state,
static gboolean
PowerOpsScriptCallback(GPid pid,
- gint exitcode,
+ gint exitStatus,
gpointer _state)
{
PowerOpState *state = _state;
- gboolean success = exitcode == 0;
+ gboolean success = exitStatus == 0;
ASSERT(state->pid != INVALID_PID);
- g_debug("Script exit code: %d, success = %d\n", exitcode, success);
+ if (WIFEXITED(exitStatus)) {
+ g_message("Script exit code: %d, success = %d\n",
+ WEXITSTATUS(exitStatus), success);
+ } else if (WIFSIGNALED(exitStatus)) {
+ g_message("Script killed by signal: %d, success = %d\n",
+ WTERMSIG(exitStatus), success);
+ } else if (WIFSTOPPED(exitStatus)) {
+ g_message("Script stopped by signal: %d, success = %d\n",
+ WSTOPSIG(exitStatus), success);
+ } else {
+ g_message("Script exit status: %d, success = %d\n", exitStatus, success);
+ }
PowerOpsStateChangeDone(_state, success);
g_spawn_close_pid(state->pid);
state->pid = INVALID_PID;
@@ -364,6 +376,7 @@ PowerOpsRunScript(PowerOpState *state,
}
argv[1] = NULL;
+ g_message("Executing script: '%s'\n", script);
if (!g_spawn_async(NULL,
argv,
NULL,
diff --git a/open-vm-tools/services/plugins/resolutionSet/resolutionSet.c b/open-vm-tools/services/plugins/resolutionSet/resolutionSet.c
index 0dec264b..92e03146 100644
--- a/open-vm-tools/services/plugins/resolutionSet/resolutionSet.c
+++ b/open-vm-tools/services/plugins/resolutionSet/resolutionSet.c
@@ -571,9 +571,9 @@ ToolsOnLoad(ToolsAppCtx *ctx)
* in calls to ResolutionSetServerCapability().
*/
- if (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) == 0) {
+ if (TOOLS_IS_MAIN_SERVICE(ctx)) {
rpcChannelName = TOOLS_DAEMON_NAME;
- } else if (strcmp(ctx->name, VMTOOLS_USER_SERVICE) == 0) {
+ } else if (TOOLS_IS_USER_SERVICE(ctx)) {
rpcChannelName = TOOLS_DND_NAME;
} else {
NOT_REACHED();
diff --git a/open-vm-tools/services/plugins/resolutionSet/resolutionX11.c b/open-vm-tools/services/plugins/resolutionSet/resolutionX11.c
index 292ad1b6..920e2367 100644
--- a/open-vm-tools/services/plugins/resolutionSet/resolutionX11.c
+++ b/open-vm-tools/services/plugins/resolutionSet/resolutionX11.c
@@ -25,6 +25,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "resolutionInt.h"
#include "resolutionRandR12.h"
@@ -38,11 +40,11 @@
#include "vmware.h"
#include "debug.h"
-#include "fileIO.h"
#include "libvmwarectrl.h"
#include "str.h"
#include "strutil.h"
#include "util.h"
+#include "posix.h"
#define VMWAREDRV_PATH_64 "/usr/X11R6/lib64/modules/drivers/vmware_drv.o"
#define VMWAREDRV_PATH "/usr/X11R6/lib/modules/drivers/vmware_drv.o"
@@ -333,14 +335,13 @@ static Bool
ResolutionCanSet(void)
{
ResolutionInfoX11Type *resInfoX = &resolutionInfoX11;
- FileIODescriptor fd;
- FileIOResult res;
- int64 filePos = 0;
+ int fd = -1;
+ off_t filePos = 0;
Bool keepSearching = TRUE;
Bool found = FALSE;
char buf[sizeof VERSION_STRING + 10]; // size of VERSION_STRING plus some extra for the version number
const char versionString[] = VERSION_STRING;
- size_t bytesRead;
+ ssize_t bytesRead;
int32 major, minor, level;
unsigned int tokPos;
@@ -411,18 +412,17 @@ ResolutionCanSet(void)
*/
buf[sizeof buf - 1] = '\0';
- FileIO_Invalidate(&fd);
- res = FileIO_Open(&fd, VMWAREDRV_PATH_64, FILEIO_ACCESS_READ, FILEIO_OPEN);
- if (res != FILEIO_SUCCESS) {
- res = FileIO_Open(&fd, VMWAREDRV_PATH, FILEIO_ACCESS_READ, FILEIO_OPEN);
+ fd = Posix_Open(VMWAREDRV_PATH_64, O_RDONLY);
+ if (fd == -1) {
+ fd = Posix_Open(VMWAREDRV_PATH, O_RDONLY);
}
- if (res == FILEIO_SUCCESS) {
+ if (fd != -1) {
/*
* One of the opens succeeded, so start searching thru the file.
*/
while (keepSearching) {
- res = FileIO_Read(&fd, buf, sizeof buf - 1, &bytesRead);
- if (res != FILEIO_SUCCESS || bytesRead < sizeof buf -1 ) {
+ bytesRead = read(fd, buf, sizeof buf - 1);
+ if (bytesRead == -1 || bytesRead < sizeof buf -1 ) {
keepSearching = FALSE;
} else {
if (Str_Strncmp(versionString, buf, sizeof versionString - 1) == 0) {
@@ -430,17 +430,17 @@ ResolutionCanSet(void)
found = TRUE;
}
}
- filePos = FileIO_Seek(&fd, filePos+1, FILEIO_SEEK_BEGIN);
+ filePos = lseek(fd, filePos+1, SEEK_SET);
if (filePos == -1) {
keepSearching = FALSE;
}
}
- FileIO_Close(&fd);
+ close(fd);
if (found) {
/*
* We NUL-terminated buf earlier, but Coverity really wants it to
- * be NUL-terminated after the call to FileIO_Read (because
- * FileIO_Read doesn't NUL-terminate). So we'll do it again.
+ * be NUL-terminated after the call to read (because
+ * read doesn't NUL-terminate). So we'll do it again.
*/
buf[sizeof buf - 1] = '\0';
diff --git a/open-vm-tools/services/plugins/timeSync/timeSync.c b/open-vm-tools/services/plugins/timeSync/timeSync.c
index 48a83ac7..57ee2545 100644
--- a/open-vm-tools/services/plugins/timeSync/timeSync.c
+++ b/open-vm-tools/services/plugins/timeSync/timeSync.c
@@ -147,6 +147,15 @@ typedef struct TimeSyncData {
GSource *timer;
} TimeSyncData;
+/*
+ * See bug 1395378
+ * Set default value to FALSE. This serves two purposes.
+ * 1) If the VMX is current, it would send the value derived from the vmx
+ * configuration and override this value.
+ * 2) If the VMX is old, the default value shall allow us not to roll back
+ * the guest clock when tools starts up.
+ */
+gboolean gTimeSyncToolsStartupAllowBackward = FALSE;
static void TimeSyncSetSlewState(TimeSyncData *data, gboolean active);
static void TimeSyncResetSlew(TimeSyncData *data);
@@ -836,6 +845,10 @@ TimeSyncSetOption(gpointer src,
}
}
+ } else if (strcmp(option, TOOLSOPTION_SYNCTIME_STARTUP_BACKWARD) == 0) {
+ if (!ParseBoolOption(value, &gTimeSyncToolsStartupAllowBackward)) {
+ return FALSE;
+ }
} else if (strcmp(option, TOOLSOPTION_SYNCTIME_STARTUP) == 0) {
static gboolean doneAlready = FALSE;
gboolean doSync;
@@ -845,7 +858,8 @@ TimeSyncSetOption(gpointer src,
}
if (doSync && !doneAlready &&
- !TimeSyncDoSync(data->slewCorrection, TRUE, TRUE, data)) {
+ !TimeSyncDoSync(data->slewCorrection, TRUE,
+ gTimeSyncToolsStartupAllowBackward, data)) {
g_warning("Unable to sync time during startup.\n");
return FALSE;
}
@@ -932,4 +946,3 @@ ToolsOnLoad(ToolsAppCtx *ctx)
return &regData;
}
-
diff --git a/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c b/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c
index d04183a7..317df958 100644
--- a/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c
+++ b/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c
@@ -55,6 +55,9 @@
#include "vm_version.h"
#include "message.h"
+#define G_LOG_DOMAIN "vix"
+#include <glib.h>
+
#include "vixPluginInt.h"
#include "vmware/tools/utils.h"
@@ -354,7 +357,7 @@ abort:
void
FoundryToolsDaemon_Initialize(ToolsAppCtx *ctx)
{
- thisProcessRunsAsRoot = (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) == 0);
+ thisProcessRunsAsRoot = TOOLS_IS_MAIN_SERVICE(ctx);
/*
* TODO: Add the original/native environment (envp) to ToolsAppContext so
@@ -443,7 +446,6 @@ ToolsDaemonTcloGetQuotedString(const char *args, // IN
{
char *resultStr = NULL;
char *endStr;
- Debug(">ToolsDaemonTcloGetQuotedString\n");
while ((*args) && ('\"' != *args)) {
args++;
@@ -475,7 +477,6 @@ ToolsDaemonTcloGetQuotedString(const char *args, // IN
*endOfArg = args;
}
- Debug("<ToolsDaemonTcloGetQuotedString\n");
return resultStr;
} // ToolsDaemonTcloGetQuotedString
@@ -552,8 +553,6 @@ ToolsDaemonTcloSyncDriverFreeze(RpcInData *data)
GKeyFile *confDictRef = ctx->config;
Bool enableNullDriver;
GSource *timer;
-
- Debug(">ToolsDaemonTcloSyncDriverFreeze\n");
/*
* Parse the arguments
@@ -566,18 +565,19 @@ ToolsDaemonTcloSyncDriverFreeze(RpcInData *data)
*/
if (NULL == driveList || NULL == timeout) {
err = VIX_E_INVALID_ARG;
- Debug("ToolsDaemonTcloSyncDriverFreeze: Failed to get string args\n");
+ g_warning("%s: Failed to get string args\n", __FUNCTION__);
goto abort;
}
if (!StrUtil_StrToInt(&timeoutVal, timeout) || timeoutVal < 0) {
- Debug("ToolsDaemonTcloSyncDriverFreeze: Bad args, timeout '%s'\n", timeout);
+ g_warning("%s: Bad args, timeout '%s'\n",
+ __FUNCTION__, timeout);
err = VIX_E_INVALID_ARG;
goto abort;
}
- Debug("SYNCDRIVE: Got request to freeze '%s', timeout %d\n", driveList,
- timeoutVal);
+ g_debug("%s: Got request to freeze '%s', timeout %d\n",
+ __FUNCTION__, driveList, timeoutVal);
/* Disallow multiple freeze calls. */
if (gSyncDriverHandle != SYNCDRIVER_INVALID_HANDLE) {
@@ -593,8 +593,8 @@ ToolsDaemonTcloSyncDriverFreeze(RpcInData *data)
/* Perform the actual freeze. */
if (!SyncDriver_Freeze(driveList, enableNullDriver, &gSyncDriverHandle) ||
SyncDriver_QueryStatus(gSyncDriverHandle, INFINITE) != SYNCDRIVER_IDLE) {
- Debug("ToolsDaemonTcloSyncDriverFreeze: Failed to Freeze drives '%s'\n",
- driveList);
+ g_warning("%s: Failed to Freeze drives '%s'\n",
+ __FUNCTION__, driveList);
err = VIX_E_FAIL;
sysError = SYNCDRIVERERROR;
if (gSyncDriverHandle != SYNCDRIVER_INVALID_HANDLE) {
@@ -606,7 +606,8 @@ ToolsDaemonTcloSyncDriverFreeze(RpcInData *data)
/* Start the timer callback to automatically thaw. */
if (0 != timeoutVal) {
- Debug("ToolsDaemonTcloSyncDriverFreeze: Starting timer callback %d\n", timeoutVal);
+ g_debug("%s: Starting timer callback %d\n",
+ __FUNCTION__, timeoutVal);
timer = g_timeout_source_new(timeoutVal * 10);
VMTOOLSAPP_ATTACH_SOURCE(ctx, timer, ToolsDaemonSyncDriverThawCallback, NULL, NULL);
g_source_unref(timer);
@@ -624,7 +625,7 @@ abort:
* foundry error and a guest-OS-specific error.
*/
Str_Sprintf(resultBuffer, sizeof resultBuffer, "%"FMT64"d %d", err, sysError);
- Debug("<ToolsDaemonTcloSyncDriverFreeze\n");
+ g_message("%s: returning %s\n", __FUNCTION__, resultBuffer);
return RPCIN_SETRETVALS(data, resultBuffer, TRUE);
}
#endif
@@ -651,21 +652,18 @@ abort:
static Bool
ToolsDaemonSyncDriverThawCallback(void *clientData) // IN (ignored)
{
- Debug(">ToolsDaemonSyncDriverThawCallback\n");
- Debug("ToolsDaemonSyncDriverThawCallback: Timed out waiting for thaw.\n");
+ g_debug("%s: Timed out waiting for thaw.\n", __FUNCTION__);
if (gSyncDriverHandle == SYNCDRIVER_INVALID_HANDLE) {
- Debug("<ToolsDaemonSyncDriverThawCallback\n");
- Debug("ToolsDaemonSyncDriverThawCallback: No drives are frozen.\n");
+ g_warning("%s: No drives are frozen.\n", __FUNCTION__);
goto exit;
}
if (!SyncDriver_Thaw(gSyncDriverHandle)) {
- Debug("ToolsDaemonSyncDriverThawCallback: Failed to thaw.\n");
+ g_warning("%s: Failed to thaw.\n", __FUNCTION__);
}
exit:
SyncDriver_CloseHandle(&gSyncDriverHandle);
- Debug("<ToolsDaemonSyncDriverThawCallback\n");
return TRUE;
}
#endif
@@ -695,22 +693,21 @@ ToolsDaemonTcloSyncDriverThaw(RpcInData *data) // IN
static char resultBuffer[DEFAULT_RESULT_MSG_MAX_LENGTH];
VixError err = VIX_OK;
DECLARE_SYNCDRIVER_ERROR(sysError);
- Debug(">ToolsDaemonTcloSyncDriverThaw\n");
/*
* This function has no arguments that we care about.
*/
- Debug("SYNCDRIVE: Got request to thaw\n");
+ g_debug("%s: Got request to thaw\n", __FUNCTION__);
if (gSyncDriverHandle == SYNCDRIVER_INVALID_HANDLE) {
err = VIX_E_GUEST_VOLUMES_NOT_FROZEN;
sysError = SYNCDRIVERERROR;
- Debug("ToolsDaemonTcloSyncDriverThaw: No drives are frozen.\n");
+ g_warning("%s: No drives are frozen.\n", __FUNCTION__);
} else if (!SyncDriver_Thaw(gSyncDriverHandle)) {
err = VIX_E_FAIL;
sysError = SYNCDRIVERERROR;
- Debug("ToolsDaemonTcloSyncDriverThaw: Failed to Thaw drives\n");
+ g_warning("%s: Failed to Thaw drives\n", __FUNCTION__);
}
SyncDriver_CloseHandle(&gSyncDriverHandle);
@@ -720,7 +717,7 @@ ToolsDaemonTcloSyncDriverThaw(RpcInData *data) // IN
* foundry error and a guest-OS-specific error.
*/
Str_Sprintf(resultBuffer, sizeof resultBuffer, "%"FMT64"d %d", err, sysError);
- Debug("<ToolsDaemonTcloSyncDriverThaw\n");
+ g_message("%s: returning %s\n", __FUNCTION__, resultBuffer);
return RPCIN_SETRETVALS(data, resultBuffer, TRUE);
}
#endif
@@ -748,6 +745,10 @@ ToolsDaemonTcloMountHGFS(RpcInData *data) // IN
static char resultBuffer[DEFAULT_RESULT_MSG_MAX_LENGTH];
#if defined(linux)
+#define MOUNT_PATH_BIN "/bin/mount"
+#define MOUNT_PATH_USR_BIN "/usr" MOUNT_PATH_BIN
+#define MOUNT_HGFS_ARGS " -t vmhgfs .host:/ /mnt/hgfs"
+
/*
* Look for a vmhgfs mount at /mnt/hgfs. If one exists, nothing
* else needs to be done. If one doesn't exist, then mount at
@@ -755,31 +756,76 @@ ToolsDaemonTcloMountHGFS(RpcInData *data) // IN
*/
FILE *mtab;
struct mntent *mnt;
+ Bool isFuseEnabled = TRUE;
+ int ret;
+
+ ret = system("/usr/bin/vmhgfs-fuse --enabled");
+ if (ret != 0 || WIFSIGNALED(ret) ||
+ (WIFEXITED(ret) && WEXITSTATUS(ret) != 0)) {
+ g_warning("%s: vmhgfs-fuse -> %d\n", __FUNCTION__, ret);
+ isFuseEnabled = FALSE;
+ }
+
if ((mtab = setmntent(_PATH_MOUNTED, "r")) == NULL) {
err = VIX_E_FAIL;
} else {
Bool vmhgfsMntFound = FALSE;
+ char *fsName;
+ char *fsType;
+ if (isFuseEnabled) {
+ fsName = HGFS_FUSENAME;
+ fsType = HGFS_FUSETYPE;
+ } else {
+ fsName = ".host:/";
+ fsType = HGFS_NAME;
+ }
while ((mnt = getmntent(mtab)) != NULL) {
- if ((strcmp(mnt->mnt_fsname, ".host:/") == 0) &&
- (strcmp(mnt->mnt_type, HGFS_NAME) == 0) &&
- (strcmp(mnt->mnt_dir, "/mnt/hgfs") == 0)) {
- vmhgfsMntFound = TRUE;
- break;
+ if ((strcmp(mnt->mnt_fsname, fsName) == 0) &&
+ (strcmp(mnt->mnt_type, fsType) == 0) &&
+ (strcmp(mnt->mnt_dir, HGFS_MOUNT_POINT) == 0)) {
+ vmhgfsMntFound = TRUE;
+ g_debug("%s: mnt fs %s type %s dir %s\n", __FUNCTION__,
+ mnt->mnt_fsname, mnt->mnt_type, mnt->mnt_dir);
+ break;
}
}
endmntent(mtab);
if (!vmhgfsMntFound) {
- /*
- * We need to call the mount program, not the mount system call. The
- * mount program does several additional things, like compute the mount
- * options from the contents of /etc/fstab, and invoke custom mount
- * programs like the one needed for HGFS.
- */
- int ret = system("mount -t vmhgfs .host:/ /mnt/hgfs");
+ int ret;
+
+ if (isFuseEnabled) {
+ ret =
+ system("/usr/bin/vmhgfs-fuse .host:/ /mnt/hgfs -o subtype=vmhgfs-fuse,allow_other");
+ } else {
+ const char *mountCmd = NULL;
+
+ ret = access(MOUNT_PATH_USR_BIN, F_OK);
+ if (ret == 0) {
+ mountCmd = MOUNT_PATH_USR_BIN MOUNT_HGFS_ARGS;
+ } else {
+ ret = access(MOUNT_PATH_BIN, F_OK);
+ if (ret == 0) {
+ mountCmd = MOUNT_PATH_BIN MOUNT_HGFS_ARGS;
+ } else {
+ g_warning("%s: failed to find mount -> %d\n", __FUNCTION__, errno);
+ }
+ }
+ if (ret == 0) {
+ /*
+ * We need to call the mount program, not the mount system call. The
+ * mount program does several additional things, like compute the mount
+ * options from the contents of /etc/fstab, and invoke custom mount
+ * programs like the one needed for HGFS.
+ */
+ g_debug("%s: system: %s\n", __FUNCTION__, mountCmd);
+ ret = system(mountCmd);
+ }
+ }
if (ret == -1 || WIFSIGNALED(ret) ||
- (WIFEXITED(ret) && WEXITSTATUS(ret) != 0)) {
+ (WIFEXITED(ret) && WEXITSTATUS(ret) != 0)) {
err = VIX_E_HGFS_MOUNT_FAIL;
+ g_warning("%s: vmhgfs mounting -> %d\n", __FUNCTION__, ret);
}
}
}
@@ -796,6 +842,8 @@ ToolsDaemonTcloMountHGFS(RpcInData *data) // IN
Err_Errno());
RPCIN_SETRETVALS(data, resultBuffer, TRUE);
+ g_message("%s: returning %s\n", __FUNCTION__, resultBuffer);
+
return TRUE;
} // ToolsDaemonTcloMountHGFS
@@ -861,7 +909,6 @@ ToolsDaemonHgfsImpersonated(RpcInData *data) // IN
+ STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING
+ OTHER_TEXT_SIZE;
- Debug(">ToolsDaemonHgfsImpersonated\n");
err = VIX_OK;
@@ -1002,7 +1049,7 @@ abort:
+ OTHER_TEXT_SIZE - 1] = '#';
}
- Debug("<<<ToolsDaemonHgfsImpersonated\n");
+ g_message("%s\n", __FUNCTION__);
return TRUE;
} // ToolsDaemonHgfsImpersonated
@@ -1046,7 +1093,8 @@ ToolsDaemonTcloReportProgramCompleted(const char *requestName, // IN
g_free(msg);
if (!sentResult) {
- Warning("Unable to send results from polling the result program.\n\n");
+ g_warning("%s: Unable to send results from polling the result program.\n",
+ __FUNCTION__);
}
} // ToolsDaemonTcloReportProgramCompleted
@@ -1132,7 +1180,11 @@ ToolsDaemonTcloReceiveVixCommand(RpcInData *data) // IN
* additional error to be sent back to VMX.
*/
additionalError = VixTools_GetAdditionalError(requestMsg->opCode, err);
- Debug("%s: additionalError = %u\n", __FUNCTION__, additionalError);
+ if (additionalError) {
+ g_message("%s: additionalError = %u\n", __FUNCTION__, additionalError);
+ } else {
+ g_debug("%s: additionalError = %u\n", __FUNCTION__, additionalError);
+ }
abort:
tcloBufferLen = resultValueLength + vixPrefixDataSize;
@@ -1191,7 +1243,6 @@ abort:
}
free(requestName);
- Debug("<ToolsDaemonTcloReceiveVixCommand\n");
return TRUE;
} // ToolsDaemonTcloReceiveVixCommand
diff --git a/open-vm-tools/services/plugins/vix/vixPlugin.c b/open-vm-tools/services/plugins/vix/vixPlugin.c
index 68eb552d..9448a656 100644
--- a/open-vm-tools/services/plugins/vix/vixPlugin.c
+++ b/open-vm-tools/services/plugins/vix/vixPlugin.c
@@ -119,7 +119,7 @@ ToolsOnLoad(ToolsAppCtx *ctx)
FoundryToolsDaemon_Initialize(ctx);
regData.regs = VMTools_WrapArray(regs, sizeof *regs, ARRAYSIZE(regs));
- if (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) == 0 && SyncDriver_Init()) {
+ if (TOOLS_IS_MAIN_SERVICE(ctx) && SyncDriver_Init()) {
size_t i;
size_t reg;
diff --git a/open-vm-tools/services/plugins/vix/vixTools.c b/open-vm-tools/services/plugins/vix/vixTools.c
index d9b4e14a..3b195540 100644
--- a/open-vm-tools/services/plugins/vix/vixTools.c
+++ b/open-vm-tools/services/plugins/vix/vixTools.c
@@ -34,6 +34,18 @@
*
*/
+/*
+ * Logging messages:
+ *
+ * All guestOps should log some common information:
+ *
+ * g_debug() of the operation and arguments for that guestop.
+ * This data could be considered sensitive so it should not be visible
+ * at default logging levels.
+ * g_message() of the operation and its VIX return code.
+ *
+ */
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -72,8 +84,6 @@
#include "dynarray.h"
#define G_LOG_DOMAIN "vix"
-#define Debug g_debug
-#define Warning g_warning
#include <glib.h>
#include "util.h"
@@ -166,6 +176,12 @@ static VGAuthUserHandle *currentUserHandle = NULL;
#endif
+/*
+ * This should be an allocated string containing the impersonated username
+ * while impersonation is active, and NULL when its not.
+ */
+char *gImpersonatedUsername = NULL;
+
#define SECONDS_BETWEEN_POLL_TEST_FINISHED 1
@@ -274,13 +290,15 @@ typedef struct VixToolsStartProgramState {
* followed immediately by a ListProcesses could miss the program
* if we don't save it off for before the timer fires.
*
+ * This data is also useful to optimize ListProcessesEx.
+ *
* Note that we save off the procState so that we keep an open
* handle to the process, to prevent its PID from being recycled.
* We need to hold this open until we no longer save the result
* of the exited program. This is documented as 5 minutes
* (VIX_TOOLS_EXITED_PROGRAM_REAP_TIME) in the VMODL.
*/
-typedef struct VixToolsExitedProgramState {
+typedef struct VixToolsStartedProgramState {
char *cmdName;
char *fullCommandLine;
char *user;
@@ -290,13 +308,13 @@ typedef struct VixToolsExitedProgramState {
time_t endTime;
Bool isRunning;
ProcMgr_AsyncProc *procState;
- struct VixToolsExitedProgramState *next;
-} VixToolsExitedProgramState;
+ struct VixToolsStartedProgramState *next;
+} VixToolsStartedProgramState;
-static VixToolsExitedProgramState *exitedProcessList = NULL;
+static VixToolsStartedProgramState *startedProcessList = NULL;
/*
- * How long we keep the info of exited processes about.
+ * How long we keep the info of exited processes.
*/
#define VIX_TOOLS_EXITED_PROGRAM_REAP_TIME (5 * 60)
@@ -455,8 +473,8 @@ static VixError VixToolsGetTempFile(VixCommandRequestHeader *requestMsg,
static void VixToolsFreeRunProgramState(VixToolsRunProgramState *asyncState);
static void VixToolsFreeStartProgramState(VixToolsStartProgramState *asyncState);
-static void VixToolsUpdateExitedProgramList(VixToolsExitedProgramState *state);
-static void VixToolsFreeExitedProgramState(VixToolsExitedProgramState *state);
+static void VixToolsUpdateStartedProgramList(VixToolsStartedProgramState *state);
+static void VixToolsFreeStartedProgramState(VixToolsStartedProgramState *state);
static VixError VixToolsStartProgramImpl(const char *requestName,
const char *programPath,
@@ -749,8 +767,7 @@ VixTools_Uninitialize(void) // IN
g_source_unref(gHgfsSessionInvalidatorTimer);
gHgfsSessionInvalidatorTimer = NULL;
gHgfsSessionInvalidatorTimerId = 0;
- Log("%s: HGFS session Invalidator detached\n",
- __FUNCTION__);
+ g_message("%s: HGFS session Invalidator detached\n", __FUNCTION__);
}
HgfsServerManager_Unregister(&gVixHgfsBkdrConn);
@@ -995,8 +1012,8 @@ VixTools_SetConsoleUserPolicy(Bool allowConsoleUserOpsParam) // IN
* Register a callback that reports when a program has completed.
* Different clients of this library will use different IPC mechanisms for
* sending this message. For example, it may use the backdoor or a socket.
- * Different sockets may use different message protocols, such as the backdoor-on-a-socket
- * or the Foundry network message.
+ * Different sockets may use different message protocols, such as the
+ * backdoor-on-a-socket or the Foundry network message.
*
* Return value:
* None
@@ -1111,6 +1128,9 @@ abort:
Str_Sprintf(resultBuffer, sizeof(resultBuffer), "%"FMT64"d", pid);
*result = resultBuffer;
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixTools_RunProgram
@@ -1153,7 +1173,7 @@ VixTools_StartProgram(VixCommandRequestHeader *requestMsg, // IN
int i;
void *userToken = NULL;
static char resultBuffer[32]; // more than enough to hold a 64 bit pid
- VixToolsExitedProgramState *exitState;
+ VixToolsStartedProgramState *spState;
VMAutomationRequestParser parser;
err = VMAutomationRequestParserInit(&parser,
@@ -1228,10 +1248,10 @@ VixTools_StartProgram(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
- Debug("%s: args: progamPath: '%s', arguments: '%s'', workingDir: %s'\n",
- __FUNCTION__, programPath,
- (NULL != arguments) ? arguments : "",
- (NULL != workingDir) ? workingDir : "");
+ g_debug("%s: User: %s args: progamPath: '%s', arguments: '%s', workingDir: '%s'\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, programPath,
+ (NULL != arguments) ? arguments : "",
+ (NULL != workingDir) ? workingDir : "");
err = VixToolsStartProgramImpl(requestName,
programPath,
@@ -1252,7 +1272,7 @@ VixTools_StartProgram(VixCommandRequestHeader *requestMsg, // IN
* We store it here to avoid the hole between starting it and the
* exited process polling proc.
*/
- exitState = Util_SafeMalloc(sizeof(VixToolsExitedProgramState));
+ spState = Util_SafeMalloc(sizeof(VixToolsStartedProgramState));
/*
* Build up the command line so the args are passed to the command.
@@ -1263,21 +1283,21 @@ VixTools_StartProgram(VixCommandRequestHeader *requestMsg, // IN
* Linux.
*/
if (NULL != arguments) {
- exitState->fullCommandLine = Str_SafeAsprintf(NULL,
- "\"%s\" %s",
- programPath,
- arguments);
+ spState->fullCommandLine = Str_SafeAsprintf(NULL,
+ "\"%s\" %s",
+ programPath,
+ arguments);
} else {
- exitState->fullCommandLine = Str_SafeAsprintf(NULL,
- "\"%s\"",
- programPath);
+ spState->fullCommandLine = Str_SafeAsprintf(NULL,
+ "\"%s\"",
+ programPath);
}
#if defined(_WIN32)
/*
* For windows, we let the VIX client parse the
* command line to get the real command name.
*/
- exitState->cmdName = NULL;
+ spState->cmdName = NULL;
#else
/*
* Find the last path separator, to get the cmd name.
@@ -1292,21 +1312,19 @@ VixTools_StartProgram(VixCommandRequestHeader *requestMsg, // IN
*/
cmdNameBegin++;
}
- exitState->cmdName = Str_SafeAsprintf(NULL,
- "%s",
- cmdNameBegin);
+ spState->cmdName = Str_SafeAsprintf(NULL, "%s", cmdNameBegin);
#endif
- exitState->user = VixToolsGetImpersonatedUsername(&userToken);
- exitState->pid = (uint64) pid;
- exitState->startTime = time(NULL);
- exitState->exitCode = 0;
- exitState->endTime = 0;
- exitState->isRunning = TRUE;
- exitState->next = NULL;
- exitState->procState = NULL;
+ spState->user = VixToolsGetImpersonatedUsername(&userToken);
+ spState->pid = (uint64) pid;
+ spState->startTime = time(NULL);
+ spState->exitCode = 0;
+ spState->endTime = 0;
+ spState->isRunning = TRUE;
+ spState->next = NULL;
+ spState->procState = NULL;
- // add it to the list of exited programs
- VixToolsUpdateExitedProgramList(exitState);
+ // add it to the list of started programs
+ VixToolsUpdateStartedProgramList(spState);
}
abort:
@@ -1320,6 +1338,11 @@ abort:
free((char **) envVars);
+ g_debug("%s: returning '%s'\n", __FUNCTION__, resultBuffer);
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixTools_StartProgram
@@ -1522,6 +1545,8 @@ abort:
VixToolsFreeRunProgramState(asyncState);
}
+ g_message("%s returning %"FMT64"d\n", __FUNCTION__, err);
+
return err;
} // VixToolsRunProgramImpl
@@ -1637,7 +1662,7 @@ VixToolsStartProgramImpl(const char *requestName, // IN
char *username = NULL;
if (!ProcMgr_GetImpersonatedUserInfo(&username, &workingDirectory)) {
- Debug("%s: ProcMgr_GetImpersonatedUserInfo() failed fetching workingDirectory\n", __FUNCTION__);
+ g_warning("%s: ProcMgr_GetImpersonatedUserInfo() failed fetching workingDirectory\n", __FUNCTION__);
err = VIX_E_FAIL;
goto abort;
}
@@ -1747,7 +1772,8 @@ VixToolsStartProgramImpl(const char *requestName, // IN
*pid = (int64) ProcMgr_GetPid(asyncState->procState);
}
- Debug("%s started '%s', pid %"FMT64"d\n", __FUNCTION__, fullCommandLine, *pid);
+ g_debug("%s: started '%s', pid %"FMT64"d\n",
+ __FUNCTION__, fullCommandLine, *pid);
/*
* Start a periodic procedure to check the app periodically
@@ -1829,8 +1855,8 @@ VixToolsMonitorAsyncProc(void *clientData) // IN
procIsRunning = ProcMgr_IsAsyncProcRunning(asyncState->procState);
if (!procIsRunning) {
if (gRestrictCommands) {
- Debug("%s: Deferring RunScript cleanup due to IO freeze\n",
- __FUNCTION__);
+ g_debug("%s: Deferring RunScript cleanup due to IO freeze\n",
+ __FUNCTION__);
} else {
goto cleanup;
}
@@ -1907,8 +1933,8 @@ VixToolsInvalidateInactiveHGFSSessions(void *clientData) // IN:
return TRUE;
} else {
- Log("%s: HGFS session Invalidator is successfully detached\n",
- __FUNCTION__);
+ g_debug("%s: HGFS session Invalidator is successfully detached\n",
+ __FUNCTION__);
g_source_unref(gHgfsSessionInvalidatorTimer);
gHgfsSessionInvalidatorTimer = NULL;
@@ -1960,8 +1986,7 @@ VixToolsRegisterHgfsSessionInvalidator(void *clientData) // IN:
g_source_attach(gHgfsSessionInvalidatorTimer,
g_main_loop_get_context((GMainLoop *) clientData));
- Log("%s: HGFS session Invalidator registered\n",
- __FUNCTION__);
+ g_debug("%s: HGFS session Invalidator registered\n", __FUNCTION__);
}
@@ -1992,7 +2017,7 @@ VixToolsMonitorStartProgram(void *clientData) // IN
int exitCode = 0;
ProcMgr_Pid pid = -1;
int result = -1;
- VixToolsExitedProgramState *exitState;
+ VixToolsStartedProgramState *spState;
GSource *timer;
asyncState = (VixToolsStartProgramState *) clientData;
@@ -2028,20 +2053,20 @@ done:
* progrtam started; that record will be updated with the exitCode
* and endTime.
*/
- exitState = Util_SafeMalloc(sizeof(VixToolsExitedProgramState));
- exitState->cmdName = NULL;
- exitState->fullCommandLine = NULL;
- exitState->user = NULL;
- exitState->pid = pid;
- exitState->startTime = 0;
- exitState->exitCode = exitCode;
- exitState->endTime = time(NULL);
- exitState->isRunning = FALSE;
- exitState->next = NULL;
- exitState->procState = asyncState->procState;
+ spState = Util_SafeMalloc(sizeof(VixToolsStartedProgramState));
+ spState->cmdName = NULL;
+ spState->fullCommandLine = NULL;
+ spState->user = NULL;
+ spState->pid = pid;
+ spState->startTime = 0;
+ spState->exitCode = exitCode;
+ spState->endTime = time(NULL);
+ spState->isRunning = FALSE;
+ spState->next = NULL;
+ spState->procState = asyncState->procState;
// add it to the list of exited programs
- VixToolsUpdateExitedProgramList(exitState);
+ VixToolsUpdateStartedProgramList(spState);
VixToolsFreeStartProgramState(asyncState);
@@ -2052,9 +2077,9 @@ done:
/*
*-----------------------------------------------------------------------------
*
- * VixToolsUpdateExitedProgramList --
+ * VixToolsUpdateStartedProgramList --
*
- * Adds a new exited program's state to the saved list, and
+ * Adds a new started program's state to the saved list, and
* removes any that have been there too long.
*
* Return value:
@@ -2066,11 +2091,11 @@ done:
*-----------------------------------------------------------------------------
*/
static void
-VixToolsUpdateExitedProgramList(VixToolsExitedProgramState *state) // IN
+VixToolsUpdateStartedProgramList(VixToolsStartedProgramState *state) // IN
{
- VixToolsExitedProgramState *epList = NULL;
- VixToolsExitedProgramState *last = NULL;
- VixToolsExitedProgramState *old = NULL;
+ VixToolsStartedProgramState *spList = NULL;
+ VixToolsStartedProgramState *last = NULL;
+ VixToolsStartedProgramState *old = NULL;
time_t now;
now = time(NULL);
@@ -2079,26 +2104,37 @@ VixToolsUpdateExitedProgramList(VixToolsExitedProgramState *state) // IN
* Update the 'running' record if the process has completed.
*/
if (state && (state->isRunning == FALSE)) {
- epList = exitedProcessList;
- while (epList) {
- if (epList->pid == state->pid) {
+ spList = startedProcessList;
+ while (spList) {
+ if (spList->pid == state->pid) {
/*
* Update the two exit fields now that we have them
*/
- epList->exitCode = state->exitCode;
- epList->endTime = state->endTime;
- epList->isRunning = FALSE;
- epList->procState = state->procState;
+ spList->exitCode = state->exitCode;
+ spList->endTime = state->endTime;
+ spList->isRunning = FALSE;
- // don't let the procState be free'd
+ /*
+ * Don't let the procState be free'd on Windows to
+ * keep OS from reusing the pid. We need to free
+ * procState in case of Posix to avoid unnecessary
+ * caching of FDs, which might make the service run
+ * out of FDs as FDs are limited (usually 1024 by
+ * default) for a process.
+ */
+#ifdef WIN32
+ spList->procState = state->procState;
state->procState = NULL;
+#else
+ spList->procState = NULL;
+#endif
- VixToolsFreeExitedProgramState(state);
+ VixToolsFreeStartedProgramState(state);
// NULL it out so we don't try to add it later in this function
state = NULL;
break;
} else {
- epList = epList->next;
+ spList = spList->next;
}
}
}
@@ -2108,32 +2144,33 @@ VixToolsUpdateExitedProgramList(VixToolsExitedProgramState *state) // IN
* Find and toss any old records.
*/
last = NULL;
- epList = exitedProcessList;
- while (epList) {
+ spList = startedProcessList;
+ while (spList) {
/*
* Sanity check we don't have a duplicate entry -- this should
* only happen when the OS re-uses the PID before we reap the record
* of its exit status.
*/
if (state) {
- if (state->pid == epList->pid) {
+ if (state->pid == spList->pid) {
// XXX just whine for M/N, needs better fix in *main
- Warning("%s: found duplicate entry in exitedProcessList\n", __FUNCTION__);
+ g_warning("%s: found duplicate entry in startedProcessList\n",
+ __FUNCTION__);
}
}
- if (!epList->isRunning &&
- (epList->endTime < (now - VIX_TOOLS_EXITED_PROGRAM_REAP_TIME))) {
+ if (!spList->isRunning &&
+ (spList->endTime < (now - VIX_TOOLS_EXITED_PROGRAM_REAP_TIME))) {
if (last) {
- last->next = epList->next;
+ last->next = spList->next;
} else {
- exitedProcessList = epList->next;
+ startedProcessList = spList->next;
}
- old = epList;
- epList = epList->next;
- VixToolsFreeExitedProgramState(old);
+ old = spList;
+ spList = spList->next;
+ VixToolsFreeStartedProgramState(old);
} else {
- last = epList;
- epList = epList->next;
+ last = spList;
+ spList = spList->next;
}
}
@@ -2145,17 +2182,17 @@ VixToolsUpdateExitedProgramList(VixToolsExitedProgramState *state) // IN
if (last) {
last->next = state;
} else {
- exitedProcessList = state;
+ startedProcessList = state;
}
}
-} // VixToolsUpdateExitedProgramList
+} // VixToolsUpdateStartedProgramList
/*
*-----------------------------------------------------------------------------
*
- * VixToolsFreeExitedProgramState --
+ * VixToolsFreeStartedProgramState --
*
*
* Results:
@@ -2168,28 +2205,28 @@ VixToolsUpdateExitedProgramList(VixToolsExitedProgramState *state) // IN
*/
void
-VixToolsFreeExitedProgramState(VixToolsExitedProgramState *exitState) // IN
+VixToolsFreeStartedProgramState(VixToolsStartedProgramState *spState) // IN
{
- if (NULL == exitState) {
+ if (NULL == spState) {
return;
}
- free(exitState->cmdName);
- free(exitState->fullCommandLine);
- free(exitState->user);
+ free(spState->cmdName);
+ free(spState->fullCommandLine);
+ free(spState->user);
- if (NULL != exitState->procState) {
- ProcMgr_Free(exitState->procState);
+ if (NULL != spState->procState) {
+ ProcMgr_Free(spState->procState);
}
- free(exitState);
-} // VixToolsFreeExitedProgramState
+ free(spState);
+} // VixToolsFreeStartedProgramState
/*
*-----------------------------------------------------------------------------
*
- * VixToolsFindExitedProgramState --
+ * VixToolsFindStartedProgramState --
*
* Searches the list of running/exited apps to see if the given
* pid was started via StartProgram.
@@ -2203,17 +2240,17 @@ VixToolsFreeExitedProgramState(VixToolsExitedProgramState *exitState) // IN
*-----------------------------------------------------------------------------
*/
-VixToolsExitedProgramState *
-VixToolsFindExitedProgramState(uint64 pid)
+VixToolsStartedProgramState *
+VixToolsFindStartedProgramState(uint64 pid)
{
- VixToolsExitedProgramState *epList;
+ VixToolsStartedProgramState *spList;
- epList = exitedProcessList;
- while (epList) {
- if (epList->pid == pid) {
- return epList;
+ spList = startedProcessList;
+ while (spList) {
+ if (spList->pid == pid) {
+ return spList;
}
- epList = epList->next;
+ spList = spList->next;
}
return NULL;
@@ -2289,6 +2326,7 @@ VixToolsTranslateVGAuthError(VGAuthError vgErr)
break;
case VGAUTH_E_COMM:
err = VIX_E_FAIL;
+ break;
case VGAUTH_E_NOTIMPLEMENTED:
err = VIX_E_NOT_SUPPORTED;
break;
@@ -2330,12 +2368,12 @@ VixToolsTranslateVGAuthError(VGAuthError vgErr)
break;
default:
err = VIX_E_FAIL;
- Warning("%s: error code "VGAUTHERR_FMT64X" has no translation\n",
- __FUNCTION__, vgErr);
+ g_warning("%s: error code "VGAUTHERR_FMT64X" has no translation\n",
+ __FUNCTION__, vgErr);
break;
}
- Debug("%s: translated VGAuth err "VGAUTHERR_FMT64X" to Vix err %"FMT64"d\n",
- __FUNCTION__, vgErr, err);
+ g_debug("%s: translated VGAuth err "VGAUTHERR_FMT64X" to Vix err %"FMT64"d\n",
+ __FUNCTION__, vgErr, err);
return err;
@@ -2651,7 +2689,7 @@ VixToolsSetSharedFoldersProperties(VixPropertyListImpl *propList) // IN
VixError err = VIX_OK;
/* Retrieve the share folders UNC root path. */
- Unicode hgfsRootPath = NULL;
+ char *hgfsRootPath = NULL;
if (!HgfsHlpr_QuerySharesDefaultRootPath(&hgfsRootPath)) {
/* Exit ok as we have nothing to set from shared folders. */
@@ -2662,7 +2700,7 @@ VixToolsSetSharedFoldersProperties(VixPropertyListImpl *propList) // IN
err = VixPropertyList_SetString(propList,
VIX_PROPERTY_GUEST_SHAREDFOLDERS_SHARES_PATH,
- UTF8(hgfsRootPath));
+ hgfsRootPath);
if (VIX_OK != err) {
goto exit;
}
@@ -3036,7 +3074,7 @@ VixToolsSetAPIEnabledProperties(VixPropertyListImpl *propList, // IN
goto exit;
}
exit:
- Debug("finished %s, err %"FMT64"d\n", __FUNCTION__, err);
+ g_debug("%s: returning err %"FMT64"d\n", __FUNCTION__, err);
return err;
} // VixToolsSetAPIEnabledProperties
@@ -3149,6 +3187,11 @@ abort:
}
*result = valueStr;
+ g_debug("%s: returning '%s'\n", __FUNCTION__, valueStr);
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
#else
@@ -3255,6 +3298,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
#else
@@ -3322,6 +3368,9 @@ VixToolsDeleteObject(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s path: '%s'\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, pathName);
+
///////////////////////////////////////////
if ((VIX_COMMAND_DELETE_GUEST_FILE == requestMsg->opCode) ||
(VIX_COMMAND_DELETE_GUEST_FILE_EX == requestMsg->opCode)) {
@@ -3411,6 +3460,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsDeleteObject
@@ -3478,6 +3530,9 @@ VixToolsDeleteDirectory(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s path: '%s' recursive: %d\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, directoryPath, (int) recursive);
+
success = File_Exists(directoryPath);
if (!success) {
err = FoundryToolsDaemon_TranslateSystemErr();
@@ -3522,6 +3577,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsDeleteDirectory
@@ -3586,6 +3644,9 @@ VixToolsObjectExists(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s path: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, pathName);
+
/*
* Do the action appropriate for this type of object.
*/
@@ -3628,6 +3689,11 @@ abort:
Str_Sprintf(resultBuffer, sizeof(resultBuffer), "%d", resultInt);
*result = resultBuffer;
+ g_debug("%s: returning '%s'\n", __FUNCTION__, resultBuffer);
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsObjectExists
@@ -3663,8 +3729,8 @@ VixToolsCreateTempFile(VixCommandRequestHeader *requestMsg, // IN
(VIX_COMMAND_CREATE_TEMPORARY_DIRECTORY != requestMsg->opCode)) {
ASSERT(0);
err = VIX_E_FAIL;
- Debug("%s: Received a request with an invalid opcode: %d\n",
- __FUNCTION__, requestMsg->opCode);
+ g_warning("%s: Received a request with an invalid opcode: %d\n",
+ __FUNCTION__, requestMsg->opCode);
goto abort;
}
@@ -3674,6 +3740,9 @@ VixToolsCreateTempFile(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
+
err = VixToolsGetTempFile(requestMsg, userToken, &filePathName, &fd);
if (VIX_FAILED(err)) {
goto abort;
@@ -3687,18 +3756,24 @@ VixToolsCreateTempFile(VixCommandRequestHeader *requestMsg, // IN
*/
if (fd > 0) {
if (close(fd) < 0) {
- Debug("Unable to close a file, errno is %d.\n", errno);
+ g_warning("%s: Unable to close a file, errno is %d.\n",
+ __FUNCTION__, errno);
}
}
*result = filePathName;
+ g_debug("%s: returning '%s'\n", __FUNCTION__, filePathName);
+
abort:
if (impersonatingVMWareUser) {
VixToolsUnimpersonateUser(userToken);
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsCreateTempFile
@@ -3753,6 +3828,9 @@ VixToolsReadVariable(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s var: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, valueName);
+
switch (readRequest->variableType) {
case VIX_GUEST_ENVIRONMENT_VARIABLE:
/*
@@ -3792,12 +3870,17 @@ VixToolsReadVariable(VixCommandRequestHeader *requestMsg, // IN
*result = value;
+ g_debug("%s: returning '%s'\n", __FUNCTION__, value);
+
abort:
if (impersonatingVMWareUser) {
VixToolsUnimpersonateUser(userToken);
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsReadVariable
@@ -3889,6 +3972,9 @@ VixToolsReadEnvVariables(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s reading %d vars\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, readRequest->numNames);
+
err = VMAutomationRequestParserGetOptionalStrings(&parser,
readRequest->numNames,
readRequest->namesLength,
@@ -3916,12 +4002,17 @@ VixToolsReadEnvVariables(VixCommandRequestHeader *requestMsg, // IN
*result = results;
+ g_debug("%s: returning '%s'\n", __FUNCTION__, results);
+
abort:
if (impersonatingVMWareUser) {
VixToolsUnimpersonateUser(userToken);
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsReadEnvVariables
@@ -4149,7 +4240,7 @@ VixToolsGetAllEnvVarsForUser(void *userToken, // IN
free(tmp);
free(envVar);
if (NULL == resultLocal) {
- Debug("%s: Out of memory.\n", __FUNCTION__);
+ g_warning("%s: Out of memory.\n", __FUNCTION__);
err = VIX_E_OUT_OF_MEMORY;
goto abort;
}
@@ -4206,6 +4297,9 @@ VixToolsWriteVariable(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s name: %s value %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, valueName, value);
+
switch (writeRequest->variableType) {
case VIX_GUEST_ENVIRONMENT_VARIABLE:
#if !defined(_WIN32)
@@ -4263,6 +4357,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsWriteVariable
@@ -4324,8 +4421,8 @@ VixToolsMoveObject(VixCommandRequestHeader *requestMsg) // IN
overwrite = renameRequest->overwrite;
} else {
ASSERT(0);
- Debug("%s: Invalid request with opcode %d received\n ",
- __FUNCTION__, requestMsg->opCode);
+ g_warning("%s: Invalid request with opcode %d received\n ",
+ __FUNCTION__, requestMsg->opCode);
err = VIX_E_FAIL;
goto abort;
}
@@ -4349,15 +4446,16 @@ VixToolsMoveObject(VixCommandRequestHeader *requestMsg) // IN
goto abort;
}
- Debug("%s: src = %s, dest=%s\n", __FUNCTION__, srcFilePathName,
- destFilePathName);
-
err = VixToolsImpersonateUser(requestMsg, &userToken);
if (VIX_OK != err) {
goto abort;
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s src: %s dst: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME,
+ srcFilePathName, destFilePathName);
+
if (!(File_Exists(srcFilePathName))) {
err = FoundryToolsDaemon_TranslateSystemErr();
goto abort;
@@ -4470,7 +4568,7 @@ VixToolsMoveObject(VixCommandRequestHeader *requestMsg) // IN
success = File_Move(srcFilePathName, destFilePathName, NULL);
if (!success) {
err = FoundryToolsDaemon_TranslateSystemErr();
- Debug("%s: File_Move failed.\n", __FUNCTION__);
+ g_warning("%s: File_Move failed.\n", __FUNCTION__);
goto abort;
}
@@ -4480,6 +4578,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsMoveObject
@@ -4511,6 +4612,7 @@ VixToolsInitiateFileTransferFromGuest(VixCommandRequestHeader *requestMsg, //
char *resultBuffer = NULL;
Bool impersonatingVMWareUser = FALSE;
void *userToken = NULL;
+ // re-use of ListFiles op
VixMsgListFilesRequest *commandRequest = NULL;
VMAutomationRequestParser parser;
@@ -4543,8 +4645,11 @@ VixToolsInitiateFileTransferFromGuest(VixCommandRequestHeader *requestMsg, //
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s filePath: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, filePathName);
+
if (File_IsSymLink(filePathName)){
- Debug("%s: File path cannot point to a symlink.\n", __FUNCTION__);
+ g_warning("%s: File path cannot point to a symlink.\n", __FUNCTION__);
err = VIX_E_INVALID_ARG;
goto abort;
}
@@ -4572,6 +4677,11 @@ abort:
}
*result = resultBuffer;
+ g_debug("%s: returning '%s'\n", __FUNCTION__, resultBuffer);
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsInitiateFileTransferFromGuest
@@ -4644,16 +4754,16 @@ VixToolsInitiateFileTransferToGuest(VixCommandRequestHeader *requestMsg) // IN
if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_OWNERID) ||
(fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_GROUPID) ||
(fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_PERMISSIONS)) {
- Debug("%s: Invalid attributes received for Windows Guest\n",
- __FUNCTION__);
+ g_warning("%s: Invalid attributes received for Windows Guest\n",
+ __FUNCTION__);
err = VIX_E_INVALID_ARG;
goto abort;
}
#else
if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_HIDDEN) ||
(fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_READONLY)) {
- Debug("%s: Invalid attributes received for Unix Guest\n",
- __FUNCTION__);
+ g_warning("%s: Invalid attributes received for Unix Guest\n",
+ __FUNCTION__);
err = VIX_E_INVALID_ARG;
goto abort;
}
@@ -4665,8 +4775,12 @@ VixToolsInitiateFileTransferToGuest(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s path: %s attrs: %d\n",
+ __FUNCTION__, IMPERSONATED_USERNAME,
+ guestPathName, fileAttributeOptions);
+
if (File_IsSymLink(guestPathName)) {
- Debug("%s: Filepath cannot point to a symlink.\n", __FUNCTION__);
+ g_warning("%s: Filepath cannot point to a symlink.\n", __FUNCTION__);
err = VIX_E_INVALID_ARG;
goto abort;
}
@@ -4692,8 +4806,8 @@ VixToolsInitiateFileTransferToGuest(VixCommandRequestHeader *requestMsg) // IN
* return an explicit VIX_E_FILE_ACCESS_ERROR.
*/
err = VIX_E_FILE_ACCESS_ERROR;
- Debug("Unable to get access permissions for the file: %s\n",
- guestPathName);
+ g_warning("%s: Unable to get access permissions for the file: %s\n",
+ __FUNCTION__, guestPathName);
}
}
goto abort;
@@ -4751,8 +4865,8 @@ VixToolsInitiateFileTransferToGuest(VixCommandRequestHeader *requestMsg) // IN
* to translate the errno to a proper foundry error.
*/
err = Vix_TranslateErrno(errno);
- Debug("Unable to create a temp file to test directory permissions,"
- " errno is %d\n", errno);
+ g_warning("%s: Unable to create a temp file to test directory "
+ "permissions, errno is %d\n", __FUNCTION__, errno);
goto abort;
}
@@ -4775,8 +4889,8 @@ VixToolsInitiateFileTransferToGuest(VixCommandRequestHeader *requestMsg) // IN
* return an explicit VIX_E_FILE_ACCESS_ERROR.
*/
err = VIX_E_FILE_ACCESS_ERROR;
- Debug("Unable to get access permissions for the directory: %s\n",
- dirName);
+ g_warning("%s: Unable to get access permissions for the directory: %s\n",
+ __FUNCTION__, dirName);
goto abort;
}
#endif
@@ -4790,6 +4904,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsInitiateFileTransferToGuest
@@ -4844,6 +4961,9 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s \n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
+
escapeStrs = (requestMsg->requestFlags &
VIX_REQUESTMSG_ESCAPE_XML_DATA) != 0;
@@ -4966,6 +5086,11 @@ abort:
*result = resultBuffer;
+ // XXX result too large for g_debug()
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return(err);
} // VixToolsListProcesses
@@ -5023,8 +5148,8 @@ VixToolsListProcCacheCleanup(void *clientData) // IN
gboolean ret;
ret = g_hash_table_remove(listProcessesResultsTable, &key);
- Debug("%s: list proc cache timed out, purged key %d (found? %d)\n",
- __FUNCTION__, key, ret);
+ g_debug("%s: list proc cache timed out, purged key %d (found? %d)\n",
+ __FUNCTION__, key, ret);
return FALSE;
}
@@ -5056,7 +5181,8 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN
ProcMgrProcInfoArray *procList = NULL;
ProcMgrProcInfo *procInfo;
DynBuf dynBuffer;
- VixToolsExitedProgramState *epList;
+ VixToolsStartedProgramState *spList;
+ int numReported = 0;
int i;
int j;
Bool bRet;
@@ -5065,61 +5191,75 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN
DynBuf_Init(&dynBuffer);
/*
- * XXX optimize -- we should only do this if we can't find
- * all requested processes on the exitedProcessList, which is
- * a common case, when a client is watching for a single pid
- * from StartProgram to exit.
- */
- procList = ProcMgr_ListProcesses();
- if (NULL == procList) {
- err = FoundryToolsDaemon_TranslateSystemErr();
- goto abort;
- }
-
- /*
* First check the processes we've started via StartProgram, which
* will find those running and recently deceased.
*/
- VixToolsUpdateExitedProgramList(NULL);
+ VixToolsUpdateStartedProgramList(NULL);
if (numPids > 0) {
for (i = 0; i < numPids; i++) {
- epList = exitedProcessList;
- while (epList) {
- if (pids[i] == epList->pid) {
+ spList = startedProcessList;
+ while (spList) {
+ if (pids[i] == spList->pid) {
err = VixToolsPrintProcInfoEx(&dynBuffer,
- epList->cmdName,
- epList->fullCommandLine,
- epList->pid,
- epList->user,
- (int) epList->startTime,
- epList->exitCode,
- (int) epList->endTime);
+ spList->cmdName,
+ spList->fullCommandLine,
+ spList->pid,
+ spList->user,
+ (int) spList->startTime,
+ spList->exitCode,
+ (int) spList->endTime);
if (VIX_OK != err) {
goto abort;
}
+ numReported++;
break;
}
- epList = epList->next;
+ spList = spList->next;
}
}
} else {
- epList = exitedProcessList;
- while (epList) {
+ spList = startedProcessList;
+ while (spList) {
err = VixToolsPrintProcInfoEx(&dynBuffer,
- epList->cmdName,
- epList->fullCommandLine,
- epList->pid,
- epList->user,
- (int) epList->startTime,
- epList->exitCode,
- (int) epList->endTime);
+ spList->cmdName,
+ spList->fullCommandLine,
+ spList->pid,
+ spList->user,
+ (int) spList->startTime,
+ spList->exitCode,
+ (int) spList->endTime);
if (VIX_OK != err) {
goto abort;
}
- epList = epList->next;
+ spList = spList->next;
}
}
+ /*
+ * If we found data for all requested processes from the startedProcess
+ * list, then we're done.
+ */
+ if (numPids > 0 && (numPids == numReported)) {
+ g_debug("%s: found all %d requested pids on the startedProcess list; finished\n",
+ __FUNCTION__, numPids);
+ goto done;
+ }
+
+ /*
+ * The startedProcess list didn't give everything we need, so
+ * ask the OS.
+ *
+ * XXX Need a smarter version of ProcMgr_ListProcesses().
+ * It should allow a list of pids for optimization, and
+ * return an error code so there's no risk of errno/LastError
+ * being clobbered.
+ */
+ procList = ProcMgr_ListProcesses();
+ if (NULL == procList) {
+ err = FoundryToolsDaemon_TranslateSystemErr();
+ goto abort;
+ }
+
/*
* Now look at the running list. Note that we set endTime
@@ -5130,8 +5270,8 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN
procCount = ProcMgrProcInfoArray_Count(procList);
if (numPids > 0) {
for (i = 0; i < numPids; i++) {
- // ignore it if its on the exited list -- we added it above
- if (VixToolsFindExitedProgramState(pids[i])) {
+ // ignore it if its on the started list -- we added it above
+ if (VixToolsFindStartedProgramState(pids[i])) {
continue;
}
for (j = 0; j < procCount; j++) {
@@ -5154,8 +5294,8 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN
} else {
for (i = 0; i < procCount; i++) {
procInfo = ProcMgrProcInfoArray_AddressOf(procList, i);
- // ignore it if its on the exited list -- we added it above
- if (VixToolsFindExitedProgramState(procInfo->procId)) {
+ // ignore it if its on the started list -- we added it above
+ if (VixToolsFindStartedProgramState(procInfo->procId)) {
continue;
}
err = VixToolsPrintProcInfoEx(&dynBuffer,
@@ -5172,6 +5312,8 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN
}
}
+done:
+
// add the final NUL
bRet = DynBuf_Append(&dynBuffer, "", 1);
if (!bRet) {
@@ -5252,6 +5394,9 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
+
#if defined(__APPLE__)
/*
* On MacOS, to fetch info on processes owned by others
@@ -5282,7 +5427,8 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN
cachedResult = g_hash_table_lookup(listProcessesResultsTable,
&key);
if (NULL == cachedResult) {
- Debug("%s: failed to find cached data with key %d\n", __FUNCTION__, key);
+ g_warning("%s: failed to find cached data with key %d\n",
+ __FUNCTION__, key);
err = VIX_E_FAIL;
goto abort;
}
@@ -5301,7 +5447,7 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN
#ifdef _WIN32
bRet = VixToolsGetUserName(&userName);
if (!bRet) {
- Debug("%s: VixToolsGetUserName() failed\n", __FUNCTION__);
+ g_warning("%s: VixToolsGetUserName() failed\n", __FUNCTION__);
err = VIX_E_FAIL;
goto abort;
}
@@ -5310,8 +5456,8 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN
* Since this isn't user-set, assume any problem is in the
* code and return VIX_E_FAIL
*/
- Debug("%s: username mismatch validating cached data (have %S, want %S)\n",
- __FUNCTION__, userName, cachedResult->userName);
+ g_warning("%s: username mismatch validating cached data (have %S, want %S)\n",
+ __FUNCTION__, userName, cachedResult->userName);
err = VIX_E_FAIL;
goto abort;
}
@@ -5322,8 +5468,8 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN
* code and return VIX_E_FAIL
*/
err = VIX_E_FAIL;
- Debug("%s: euid mismatch validating cached data (want %d, got %d)\n",
- __FUNCTION__, (int) cachedResult->euid, (int) Id_GetEUid());
+ g_warning("%s: euid mismatch validating cached data (want %d, got %d)\n",
+ __FUNCTION__, (int) cachedResult->euid, (int) Id_GetEUid());
goto abort;
}
#endif
@@ -5348,7 +5494,8 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN
* Stuff it in the hash table if so.
*/
if ((fullResultSize + resultHeaderSize) > maxBufferSize) {
- Debug("%s: answer requires caching. have %d bytes\n", __FUNCTION__, (int) (fullResultSize + resultHeaderSize));
+ g_debug("%s: answer requires caching. have %d bytes\n",
+ __FUNCTION__, (int) (fullResultSize + resultHeaderSize));
/*
* Save it off in the hashtable.
*/
@@ -5360,7 +5507,7 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN
#ifdef _WIN32
bRet = VixToolsGetUserName(&cachedResult->userName);
if (!bRet) {
- Debug("%s: failed to get current userName\n", __FUNCTION__);
+ g_warning("%s: failed to get current userName\n", __FUNCTION__);
goto abort;
}
#else
@@ -5451,6 +5598,11 @@ abort:
*result = finalResultBuffer;
+ // XXX result too large for g_debug()
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return(err);
} // VixToolsListProcessesEx
@@ -5575,7 +5727,7 @@ VixToolsKillProcess(VixCommandRequestHeader *requestMsg) // IN
VixCommandKillProcessRequest *killProcessRequest;
#ifdef _WIN32
DWORD dwErr;
- const VixToolsExitedProgramState *exitedState;
+ const VixToolsStartedProgramState *spState;
#else
int sysErrno;
#endif
@@ -5588,6 +5740,9 @@ VixToolsKillProcess(VixCommandRequestHeader *requestMsg) // IN
killProcessRequest = (VixCommandKillProcessRequest *) requestMsg;
+ g_debug("%s: User: %s pid: %"FMT64"d\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, killProcessRequest->pid);
+
/*
* This is here for two reasons:
* 1) If you kill this process, then it cannot report back to
@@ -5606,7 +5761,7 @@ VixToolsKillProcess(VixCommandRequestHeader *requestMsg) // IN
if (!ProcMgr_KillByPid(killProcessRequest->pid)) {
/*
- * Save off the error code so any Debug() statements added later
+ * Save off the error code so any debug statements added later
* (or when debugging something else) doesn't change the error code.
*/
#ifdef _WIN32
@@ -5622,8 +5777,8 @@ VixToolsKillProcess(VixCommandRequestHeader *requestMsg) // IN
* on a process we started but is still on the 'exited' list,
* then Windows returns an ACCESS_ERROR. So rewrite it.
*/
- exitedState = VixToolsFindExitedProgramState(killProcessRequest->pid);
- if ((NULL != exitedState) && !exitedState->isRunning) {
+ spState = VixToolsFindStartedProgramState(killProcessRequest->pid);
+ if ((NULL != spState) && !spState->isRunning) {
err = VIX_E_NO_SUCH_PROCESS;
goto abort;
}
@@ -5675,6 +5830,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsKillProcess
@@ -5730,8 +5888,8 @@ VixToolsCreateDirectory(VixCommandRequestHeader *requestMsg) // IN
createParentDirectories = dirRequest->createParentDirectories;
} else {
ASSERT(0);
- Debug("%s: Invalid request with opcode %d received\n ",
- __FUNCTION__, requestMsg->opCode);
+ g_warning("%s: Invalid request with opcode %d received\n ",
+ __FUNCTION__, requestMsg->opCode);
err = VIX_E_FAIL;
goto abort;
}
@@ -5753,6 +5911,10 @@ VixToolsCreateDirectory(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s dirPathName: %s createParent: %d\n",
+ __FUNCTION__, IMPERSONATED_USERNAME,
+ dirPathName, (int) createParentDirectories);
+
if (File_Exists(dirPathName)) {
err = VIX_E_FILE_ALREADY_EXISTS;
goto abort;
@@ -5776,6 +5938,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsCreateDirectory
@@ -5872,6 +6037,9 @@ VixToolsListDirectory(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s path: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, dirPathName);
+
escapeStrs = (requestMsg->requestFlags &
VIX_REQUESTMSG_ESCAPE_XML_DATA) != 0;
@@ -5983,6 +6151,11 @@ abort:
free(fileNameList);
}
+ // XXX result too large for g_debug()
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsListDirectory
@@ -6064,8 +6237,8 @@ VixToolsListFiles(VixCommandRequestHeader *requestMsg, // IN
goto abort;
}
- Debug("%s: pattern length is %d, value is '%s'\n",
- __FUNCTION__, listRequest->patternLength, pattern);
+ g_debug("%s: pattern length is %d, value is '%s'\n",
+ __FUNCTION__, listRequest->patternLength, pattern);
}
if (0 == *dirPathName) {
@@ -6079,15 +6252,17 @@ VixToolsListFiles(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
- Debug("%s: listing files in '%s' with pattern '%s'\n",
- __FUNCTION__, dirPathName,
- (NULL != pattern) ? pattern : "");
+ g_debug("%s: User: %s listing files in '%s' with pattern '%s' "
+ "index %d, maxResults %d (offset %d)\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, dirPathName,
+ (NULL != pattern) ? pattern : "",
+ index, maxResults, (int) offset);
if (pattern) {
regex = g_regex_new(pattern, 0, 0, &gerr);
if (!regex) {
- Debug("%s: bad regex pattern '%s'; failing with INVALID_ARG\n",
- __FUNCTION__, pattern);
+ g_warning("%s: bad regex pattern '%s'; failing with INVALID_ARG\n",
+ __FUNCTION__, pattern);
err = VIX_E_INVALID_ARG;
goto abort;
}
@@ -6255,6 +6430,11 @@ abort:
free(fileNameList);
}
+ // XXX result too large for g_debug()
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsListFiles
@@ -6372,6 +6552,9 @@ VixToolsGetFileInfo(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s path: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, filePathName);
+
if (!(File_Exists(filePathName))) {
err = VIX_E_FILE_NOT_FOUND;
goto abort;
@@ -6402,6 +6585,11 @@ abort:
}
*result = resultBuffer;
+ g_debug("%s: returning '%s'\n", __FUNCTION__, resultBuffer);
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsGetFileInfo
@@ -6492,15 +6680,15 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN
if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_OWNERID) ||
(fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_GROUPID) ||
(fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_PERMISSIONS)) {
- Debug("%s: Invalid attributes received for Windows Guest\n",
- __FUNCTION__);
+ g_warning("%s: Invalid attributes received for Windows Guest\n",
+ __FUNCTION__);
err = VIX_E_INVALID_ARG;
goto abort;
}
#else
if (windowsAttributeSpecified) {
- Debug("%s: Invalid attributes received for Posix Guest\n",
- __FUNCTION__);
+ g_warning("%s: Invalid attributes received for Posix Guest\n",
+ __FUNCTION__);
err = VIX_E_INVALID_ARG;
goto abort;
}
@@ -6512,6 +6700,9 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s path: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME, filePathName);
+
if (!(File_Exists(filePathName))) {
err = FoundryToolsDaemon_TranslateSystemErr();
goto abort;
@@ -6525,7 +6716,7 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN
&tempTime);
if (!success) {
- Debug("%s: Failed to get the times.\n", __FUNCTION__);
+ g_warning("%s: Failed to get the times.\n", __FUNCTION__);
err = FoundryToolsDaemon_TranslateSystemErr();
goto abort;
}
@@ -6554,7 +6745,7 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN
modificationTime,
modificationTime);
if (!success) {
- Debug("%s: Failed to set the times.\n", __FUNCTION__);
+ g_warning("%s: Failed to set the times.\n", __FUNCTION__);
err = FoundryToolsDaemon_TranslateSystemErr();
goto abort;
}
@@ -6582,26 +6773,16 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN
if (!Win32U_SetFileAttributes(filePathName, fileAttr)) {
err = FoundryToolsDaemon_TranslateSystemErr();
- Debug("%s: Failed to set the file attributes\n", __FUNCTION__);
+ g_warning("%s: Failed to set the file attributes\n", __FUNCTION__);
goto abort;
}
} else {
err = FoundryToolsDaemon_TranslateSystemErr();
- Debug("%s: Failed to get the file attributes\n", __FUNCTION__);
+ g_warning("%s: Failed to get the file attributes\n", __FUNCTION__);
goto abort;
}
}
#else
- if (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_PERMISSIONS) {
- success = File_SetFilePermissions(filePathName,
- setGuestFileAttributesRequest->permissions);
- if (!success) {
- err = FoundryToolsDaemon_TranslateSystemErr();
- Debug("%s: Failed to set the file permissions\n", __FUNCTION__);
- goto abort;
- }
- }
-
if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_OWNERID) ||
(fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_GROUPID)) {
@@ -6610,8 +6791,8 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN
groupId = statbuf.st_gid;
} else {
err = FoundryToolsDaemon_TranslateSystemErr();
- Debug("%s: Posix_Stat(%s) failed with %d\n",
- __FUNCTION__, filePathName, errno);
+ g_warning("%s: Posix_Stat(%s) failed with %d\n",
+ __FUNCTION__, filePathName, errno);
goto abort;
}
@@ -6625,7 +6806,21 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN
if (Posix_Chown(filePathName, ownerId, groupId)) {
err = FoundryToolsDaemon_TranslateSystemErr();
- Debug("%s: Failed to set the owner/group Id\n", __FUNCTION__);
+ g_warning("%s: Failed to set the owner/group Id\n", __FUNCTION__);
+ goto abort;
+ }
+ }
+
+ /*
+ * NOTE: Setting ownership clears SUID and SGID bits, therefore set the
+ * file permissions after setting ownership.
+ */
+ if (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_PERMISSIONS) {
+ success = File_SetFilePermissions(filePathName,
+ setGuestFileAttributesRequest->permissions);
+ if (!success) {
+ err = FoundryToolsDaemon_TranslateSystemErr();
+ g_warning("%s: Failed to set the file permissions\n", __FUNCTION__);
goto abort;
}
}
@@ -6637,6 +6832,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsSetGuestFileAttributes
@@ -6802,8 +7000,8 @@ VixToolsPrintFileExtendedInfo(const char *filePathName, // IN
modTime = statbuf.st_mtime;
accessTime = statbuf.st_atime;
} else {
- Debug("%s: Posix_Stat(%s) failed with %d\n",
- __FUNCTION__, filePathName, errno);
+ g_warning("%s: Posix_Stat(%s) failed with %d\n",
+ __FUNCTION__, filePathName, errno);
}
escapedFileName = VixToolsEscapeXMLString(fileName);
@@ -7005,8 +7203,11 @@ VixToolsRunScript(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
+
-if (0 == *interpreterName) {
+ if (0 == *interpreterName) {
#ifdef _WIN32
//interpreterName = "cmd.exe";
fileSuffix = ".bat";
@@ -7081,9 +7282,6 @@ if (0 == *interpreterName) {
#if defined(_WIN32)
| O_BINARY
#endif
-#if defined(linux) && defined(GLIBC_VERSION_21)
- | O_LARGEFILE
-#endif
| O_RDWR,
0600);
if (fd >= 0) {
@@ -7118,7 +7316,8 @@ if (0 == *interpreterName) {
* to translate the errno to a proper foundry error.
*/
err = Vix_TranslateErrno(errno);
- Debug("Unable to create a temporary file, errno is %d.\n", errno);
+ g_warning("%s: Unable to create a temporary file, errno is %d.\n",
+ __FUNCTION__, errno);
goto abort;
}
@@ -7135,9 +7334,11 @@ if (0 == *interpreterName) {
* something confusing to be reported to the user.
*/
err = Vix_TranslateErrno(errno);
- Debug("Unable to write the script to the temporary file, errno is %d.\n", errno);
+ g_warning("%s: Unable to write the script to the temporary file, errno is %d.\n",
+ __FUNCTION__, errno);
if (close(fd) < 0) {
- Debug("Unable to close a file, errno is %d\n", errno);
+ g_warning("%s: Unable to close a file, errno is %d\n",
+ __FUNCTION__, errno);
}
goto abort;
}
@@ -7153,7 +7354,8 @@ if (0 == *interpreterName) {
* of data. This can especially be observed with NFS and disk quotas."
*/
err = Vix_TranslateErrno(errno);
- Debug("Unable to close a file, errno is %d\n", errno);
+ g_warning("%s: Unable to close a file, errno is %d\n",
+ __FUNCTION__, errno);
goto abort;
}
@@ -7259,6 +7461,11 @@ abort:
Str_Sprintf(resultBuffer, sizeof(resultBuffer), "%"FMT64"d", pid);
*result = resultBuffer;
+ g_debug("%s: returning '%s'\n", __FUNCTION__, resultBuffer);
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsRunScript
@@ -7285,8 +7492,6 @@ VixToolsImpersonateUser(VixCommandRequestHeader *requestMsg, // IN
char *credentialField;
int credentialType;
- Debug(">%s\n", __FUNCTION__);
-
credentialField = ((char *) requestMsg)
+ requestMsg->commonHeader.headerLength
+ requestMsg->commonHeader.bodyLength;
@@ -7302,8 +7507,9 @@ VixToolsImpersonateUser(VixCommandRequestHeader *requestMsg, // IN
credentialField += sizeof(VixCommandTicketedSession);
if (ticketLength != strlen(credentialField)) {
- Debug("%s: Ticket Length Does Not Match Expected\n", __FUNCTION__);
- return VIX_E_INVALID_MESSAGE_BODY;
+ g_warning("%s: Ticket Length Does Not Match Expected\n", __FUNCTION__);
+ err = VIX_E_INVALID_MESSAGE_BODY;
+ goto done;
}
err = VixToolsImpersonateUserImplEx(NULL,
@@ -7320,9 +7526,10 @@ VixToolsImpersonateUser(VixCommandRequestHeader *requestMsg, // IN
/*
* Don't accept hashed shared secret if disabled.
*/
- Debug("%s: Requested authentication type has been disabled.\n",
- __FUNCTION__);
- return VIX_E_GUEST_AUTHTYPE_DISABLED;
+ g_message("%s: Requested authentication type has been disabled.\n",
+ __FUNCTION__);
+ err = VIX_E_GUEST_AUTHTYPE_DISABLED;
+ goto done;
}
}
// fall through
@@ -7384,11 +7591,19 @@ VixToolsImpersonateUser(VixCommandRequestHeader *requestMsg, // IN
* SSPI currently only supported in ticketed sessions
*/
default:
- Debug("%s: credentialType = %d\n", __FUNCTION__, credentialType);
+ g_warning("%s: Unsupported credentialType = %d\n",
+ __FUNCTION__, credentialType);
err = VIX_E_NOT_SUPPORTED;
}
- Debug("<%s\n", __FUNCTION__);
+done:
+ if (err != VIX_OK) {
+ g_warning("%s: impersonation failed (%"FMT64"d)\n",
+ __FUNCTION__, err);
+ } else {
+ g_debug("%s: successfully impersonated user %s\n", __FUNCTION__,
+ IMPERSONATED_USERNAME);
+ }
return(err);
} // VixToolsImpersonateUser
@@ -7457,7 +7672,7 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN
VixError err = VIX_E_INVALID_LOGIN_CREDENTIALS;
if (NULL == userToken) {
- Debug("%s: Invalid userToken pointer\n", __FUNCTION__);
+ g_warning("%s: Invalid userToken pointer\n", __FUNCTION__);
return VIX_E_FAIL;
}
@@ -7498,6 +7713,7 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN
&& (thisProcessRunsAsRoot)) {
*userToken = PROCESS_CREATOR_USER_TOKEN;
+ gImpersonatedUsername = Util_SafeStrdup("_ROOT_");
err = VIX_OK;
goto abort;
}
@@ -7506,11 +7722,14 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN
* If the VMX asks to be root, then we allow them.
* The VMX will make sure that only it will pass this value in,
* and only when the VM and host are configured to allow this.
+ *
+ * XXX This has been deprecated XXX
*/
if ((VIX_USER_CREDENTIAL_CONSOLE_USER == credentialType)
&& ((allowConsoleUserOps) || !(thisProcessRunsAsRoot))) {
*userToken = PROCESS_CREATOR_USER_TOKEN;
+ gImpersonatedUsername = Util_SafeStrdup("_CONSOLE_USER_NAME_");
err = VIX_OK;
goto abort;
}
@@ -7543,6 +7762,7 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN
}
*userToken = PROCESS_CREATOR_USER_TOKEN;
+ gImpersonatedUsername = Util_SafeStrdup(unobfuscatedUserName);
goto abort;
} else {
@@ -7602,6 +7822,7 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN
goto abort;
}
+ gImpersonatedUsername = Util_SafeStrdup(username);
err = VIX_OK;
#else
err = VIX_E_NOT_SUPPORTED;
@@ -7644,6 +7865,7 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN
goto abort;
}
+ gImpersonatedUsername = Util_SafeStrdup(unobfuscatedUserName);
err = VIX_OK;
} else {
/*
@@ -7679,6 +7901,9 @@ abort:
void
VixToolsUnimpersonateUser(void *userToken)
{
+ free(gImpersonatedUsername);
+ gImpersonatedUsername = NULL;
+
#if SUPPORT_VGAUTH
if (NULL != currentUserHandle) {
GuestAuthUnimpersonate();
@@ -7764,8 +7989,8 @@ VixToolsGetImpersonatedUsername(void *userToken)
vgErr = VGAuth_UserHandleUsername(ctx, currentUserHandle, &userName);
if (VGAUTH_FAILED(vgErr)) {
- Warning("%s: Unable to get username from userhandle %p\n",
- __FUNCTION__, currentUserHandle);
+ g_warning("%s: Unable to get username from userhandle %p\n",
+ __FUNCTION__, currentUserHandle);
}
return userName;
}
@@ -7956,7 +8181,7 @@ VixToolsGetTempFile(VixCommandRequestHeader *requestMsg, // IN
makeTempFileRequest->directoryPathLength + 1 +
makeTempFileRequest->propertyListLength)) {
ASSERT(0);
- Debug("%s: Invalid request message received\n", __FUNCTION__);
+ g_warning("%s: Invalid request message received\n", __FUNCTION__);
err = VIX_E_INVALID_MESSAGE_BODY;
goto abort;
}
@@ -7965,7 +8190,7 @@ VixToolsGetTempFile(VixCommandRequestHeader *requestMsg, // IN
if ('\0' != *(tempPtr + makeTempFileRequest->filePrefixLength)) {
ASSERT(0);
- Debug("%s: Invalid request message received\n", __FUNCTION__);
+ g_warning("%s: Invalid request message received\n", __FUNCTION__);
err = VIX_E_INVALID_MESSAGE_BODY;
goto abort;
}
@@ -7975,7 +8200,7 @@ VixToolsGetTempFile(VixCommandRequestHeader *requestMsg, // IN
if ('\0' != *(tempPtr + makeTempFileRequest->fileSuffixLength)) {
ASSERT(0);
- Debug("%s: Invalid request message received\n", __FUNCTION__);
+ g_warning("%s: Invalid request message received\n", __FUNCTION__);
err = VIX_E_INVALID_MESSAGE_BODY;
goto abort;
}
@@ -7985,7 +8210,7 @@ VixToolsGetTempFile(VixCommandRequestHeader *requestMsg, // IN
if ('\0' != *(tempPtr + makeTempFileRequest->directoryPathLength)) {
ASSERT(0);
- Debug("%s: Invalid request message received\n", __FUNCTION__);
+ g_warning("%s: Invalid request message received\n", __FUNCTION__);
err = VIX_E_INVALID_MESSAGE_BODY;
goto abort;
}
@@ -8263,12 +8488,12 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
Bool truncated;
#endif
#if defined(_WIN32)
- Unicode *driveList = NULL;
+ char **driveList = NULL;
int numDrives = -1;
uint64 freeBytesToUser = 0;
uint64 totalBytesToUser = 0;
uint64 freeBytes = 0;
- Unicode fileSystemType;
+ char *fileSystemType;
int i;
#endif
#ifdef linux
@@ -8277,8 +8502,6 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
const char *mountfile = NULL;
#endif
- Debug(">%s\n", __FUNCTION__);
-
destPtr = resultBuffer;
*destPtr = 0;
endDestPtr = resultBuffer + sizeof(resultBuffer);
@@ -8289,14 +8512,17 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
+
escapeStrs = (requestMsg->requestFlags &
VIX_REQUESTMSG_ESCAPE_XML_DATA) != 0;
#if defined(_WIN32)
numDrives = Win32U_GetLogicalDriveStrings(&driveList);
if (-1 == numDrives) {
- Warning("unable to get drive listing: windows error code %d\n",
- GetLastError());
+ g_warning("%s: unable to get drive listing: windows error code %d\n",
+ __FUNCTION__, GetLastError());
err = FoundryToolsDaemon_TranslateSystemErr();
goto abort;
}
@@ -8318,8 +8544,8 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
totalBytesToUser = 0;
freeBytes = 0;
- Warning("unable to get drive size info: windows error code %d\n",
- GetLastError());
+ g_warning("unable to get drive size info: windows error code %d\n",
+ GetLastError());
}
// If it fails, fileSystemType will be NULL
@@ -8337,7 +8563,7 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
if ((VIX_OK != err) || truncated) {
goto abort;
}
- Unicode_Free(fileSystemType);
+ free(fileSystemType);
}
#elif defined(linux)
@@ -8346,7 +8572,7 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
fp = Posix_Setmntent(mountfile, "r");
if (fp == NULL) {
- Warning("failed to open mount file\n");
+ g_warning("failed to open mount file\n");
err = VIX_E_FILE_NOT_FOUND;
goto abort;
}
@@ -8356,8 +8582,8 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
uint64 size, freeSpace;
if (Posix_Statfs(MNTINFO_MNTPT(mnt), &statfsbuf)) {
- Warning("%s unable to stat mount point %s\n",
- __FUNCTION__, MNTINFO_MNTPT(mnt));
+ g_warning("%s unable to stat mount point %s\n",
+ __FUNCTION__, MNTINFO_MNTPT(mnt));
continue;
}
size = (uint64) statfsbuf.f_blocks * (uint64) statfsbuf.f_bsize;
@@ -8378,7 +8604,7 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
abort:
#if defined(_WIN32)
for (i = 0; i < numDrives; i++) {
- Unicode_Free(driveList[i]);
+ free(driveList[i]);
}
free(driveList);
@@ -8391,7 +8617,10 @@ abort:
*result = resultBuffer;
- Debug("<%s\n", __FUNCTION__);
+ // XXX result too large for g_debug()
+
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
return(err);
} // VixToolsListFileSystems
@@ -8460,8 +8689,8 @@ VixToolsPrintFileSystemInfo(char **destPtr, // IN/OUT
*destPtr += bytesPrinted;
} else { // out of space
**destPtr = '\0';
- Debug("%s: file system list results too large, truncating",
- __FUNCTION__);
+ g_warning("%s: file system list results too large, truncating",
+ __FUNCTION__);
*truncated = TRUE;
err = VIX_OK;
goto abort;
@@ -8500,8 +8729,6 @@ VixToolsValidateCredentials(VixCommandRequestHeader *requestMsg) // IN
void *userToken = NULL;
Bool impersonatingVMWareUser = FALSE;
- Debug(">%s\n", __FUNCTION__);
-
if (NULL == requestMsg) {
ASSERT(0);
err = VIX_E_FAIL;
@@ -8515,13 +8742,18 @@ VixToolsValidateCredentials(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
+
abort:
if (impersonatingVMWareUser) {
VixToolsUnimpersonateUser(userToken);
}
VixToolsLogoutUser(userToken);
- Debug("<%s\n", __FUNCTION__);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
}
@@ -8547,7 +8779,6 @@ VixToolsAcquireCredentials(VixCommandRequestHeader *requestMsg, // IN
char **result) // OUT
{
VixError err;
- Debug(">%s\n", __FUNCTION__);
#if !defined(_WIN32)
err = VIX_E_NOT_SUPPORTED;
@@ -8556,13 +8787,16 @@ VixToolsAcquireCredentials(VixCommandRequestHeader *requestMsg, // IN
err = VixToolsAuthenticateWithSSPI(requestMsg, eventQueue, result);
if (VIX_OK != err) {
- Debug("%s: Failed to authenticate with SSPI with error %d\n", __FUNCTION__, err);
+ g_warning("%s: Failed to authenticate with SSPI with error %d\n",
+ __FUNCTION__, err);
goto abort;
}
#endif
abort:
- Debug("<%s\n", __FUNCTION__);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
}
@@ -8587,14 +8821,15 @@ VixToolsReleaseCredentials(VixCommandRequestHeader *requestMsg) // IN
{
VixError err = VIX_OK;
- Debug(">%s\n", __FUNCTION__);
#if !defined(_WIN32)
err = VIX_E_NOT_SUPPORTED;
#else
err = VixToolsReleaseCredentialsImpl(requestMsg);
#endif
- Debug("<%s\n", __FUNCTION__);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
}
@@ -8740,6 +8975,9 @@ VixToolsSetGuestNetworkingConfig(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
+
setGuestNetworkingConfigRequest = (VixMsgSetGuestNetworkingConfigRequest *)requestMsg;
messageBody = (char *) requestMsg + sizeof(*setGuestNetworkingConfigRequest);
@@ -8827,6 +9065,9 @@ abort:
}
VixToolsLogoutUser(userToken);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
+
return err;
} // VixToolsSetGuestNetworkingConfig
@@ -8867,8 +9108,6 @@ VixToolsAddAuthAlias(VixCommandRequestHeader *requestMsg) // IN
VMAutomationRequestParser parser;
Bool impersonatingVMWareUser = FALSE;
- Debug(">%s\n", __FUNCTION__);
-
err = VMAutomationRequestParserInit(&parser, requestMsg, sizeof *req);
if (VIX_OK != err) {
goto abort;
@@ -8928,6 +9167,8 @@ VixToolsAddAuthAlias(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
/*
* For aliasStore APIs, make a fresh context so we know
* the security is correct.
@@ -8963,7 +9204,8 @@ abort:
}
VixToolsLogoutUser(userToken);
- Debug("<%s\n", __FUNCTION__);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
return err;
}
@@ -9000,8 +9242,6 @@ VixToolsRemoveAuthAlias(VixCommandRequestHeader *requestMsg) // IN
VMAutomationRequestParser parser;
Bool impersonatingVMWareUser = FALSE;
- Debug(">%s\n", __FUNCTION__);
-
err = VMAutomationRequestParserInit(&parser, requestMsg, sizeof *req);
if (VIX_OK != err) {
goto abort;
@@ -9056,6 +9296,8 @@ VixToolsRemoveAuthAlias(VixCommandRequestHeader *requestMsg) // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
/*
* For aliasStore APIs, make a fresh context so we know
* the security is correct.
@@ -9100,7 +9342,8 @@ abort:
}
VixToolsLogoutUser(userToken);
- Debug("<%s\n", __FUNCTION__);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
return err;
}
@@ -9149,8 +9392,6 @@ VixToolsListAuthAliases(VixCommandRequestHeader *requestMsg, // IN
char *escapedStr = NULL;
char *escapedStr2 = NULL;
- Debug(">%s\n", __FUNCTION__);
-
ASSERT(maxBufferSize <= GUESTMSG_MAX_IN_SIZE);
*result = NULL;
@@ -9182,6 +9423,9 @@ VixToolsListAuthAliases(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
+
/*
* For aliasStore APIs, make a fresh context so we know
* the security is correct.
@@ -9295,8 +9539,8 @@ abort:
}
VixToolsLogoutUser(userToken);
-
- Debug("<%s\n", __FUNCTION__);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
return err;
}
@@ -9344,8 +9588,6 @@ VixToolsListMappedAliases(VixCommandRequestHeader *requestMsg, // IN
char *escapedStr2 = NULL;
size_t recordSize;
- Debug(">%s\n", __FUNCTION__);
-
ASSERT(maxBufferSize <= GUESTMSG_MAX_IN_SIZE);
*result = NULL;
@@ -9365,6 +9607,9 @@ VixToolsListMappedAliases(VixCommandRequestHeader *requestMsg, // IN
}
impersonatingVMWareUser = TRUE;
+ g_debug("%s: User: %s\n",
+ __FUNCTION__, IMPERSONATED_USERNAME);
+
vgErr = TheVGAuthContext(&ctx);
if (vgErr != VGAUTH_E_OK) {
err = VixToolsTranslateVGAuthError(vgErr);
@@ -9482,7 +9727,8 @@ abort:
}
VixToolsLogoutUser(userToken);
- Debug("<%s\n", __FUNCTION__);
+ g_message("%s: opcode %d returning %"FMT64"d\n", __FUNCTION__,
+ requestMsg->opCode, err);
return err;
}
@@ -9685,9 +9931,9 @@ VixToolsDoesUsernameMatchCurrentUser(const char *username) // IN
HANDLE processToken = INVALID_HANDLE_VALUE;
PTOKEN_USER processTokenInfo = NULL;
DWORD processTokenInfoSize = 0;
- Unicode sidUserName = NULL;
+ char *sidUserName = NULL;
DWORD sidUserNameSize = 0;
- Unicode sidDomainName = NULL;
+ char *sidDomainName = NULL;
DWORD sidDomainNameSize = 0;
SID_NAME_USE sidNameUse;
@@ -9706,8 +9952,8 @@ VixToolsDoesUsernameMatchCurrentUser(const char *username) // IN
if (!retVal || !processToken) {
err = FoundryToolsDaemon_TranslateSystemErr();
- Warning("unable to open process token: windows error code %d\n",
- GetLastError());
+ g_warning("unable to open process token: windows error code %d\n",
+ GetLastError());
goto abort;
}
@@ -9721,8 +9967,8 @@ VixToolsDoesUsernameMatchCurrentUser(const char *username) // IN
if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
err = FoundryToolsDaemon_TranslateSystemErr();
- Warning("unable to get token info: windows error code %d\n",
- GetLastError());
+ g_warning("unable to get token info: windows error code %d\n",
+ GetLastError());
goto abort;
}
@@ -9735,8 +9981,8 @@ VixToolsDoesUsernameMatchCurrentUser(const char *username) // IN
processTokenInfoSize,
&processTokenInfoSize)) {
err = FoundryToolsDaemon_TranslateSystemErr();
- Warning("unable to get token info: windows error code %d\n",
- GetLastError());
+ g_warning("unable to get token info: windows error code %d\n",
+ GetLastError());
goto abort;
}
@@ -9752,8 +9998,8 @@ VixToolsDoesUsernameMatchCurrentUser(const char *username) // IN
if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
err = FoundryToolsDaemon_TranslateSystemErr();
- Warning("unable to lookup account sid: windows error code %d\n",
- GetLastError());
+ g_warning("unable to lookup account sid: windows error code %d\n",
+ GetLastError());
goto abort;
}
@@ -9768,8 +10014,8 @@ VixToolsDoesUsernameMatchCurrentUser(const char *username) // IN
&sidDomainNameSize,
&sidNameUse)) {
err = FoundryToolsDaemon_TranslateSystemErr();
- Warning("unable to lookup account sid: windows error code %d\n",
- GetLastError());
+ g_warning("unable to lookup account sid: windows error code %d\n",
+ GetLastError());
goto abort;
}
@@ -9838,7 +10084,7 @@ abort:
* been validated by guestd. Assume it is a system error.
*/
err = FoundryToolsDaemon_TranslateSystemErr();
- Warning("Unable to get the uid for username %s.\n", username);
+ g_warning("Unable to get the uid for username %s.\n", username);
goto abort;
}
@@ -10193,7 +10439,7 @@ VixTools_ProcessVixCommand(VixCommandRequestHeader *requestMsg, // IN
*deleteResultBufferResult = FALSE;
}
- Debug("%s: command %d\n", __FUNCTION__, requestMsg->opCode);
+ g_message("%s: command %d\n", __FUNCTION__, requestMsg->opCode);
/*
* PR 1210773: Check if new VIX commands can be processed.
@@ -10217,8 +10463,8 @@ VixTools_ProcessVixCommand(VixCommandRequestHeader *requestMsg, // IN
* in a graceful manner.
*/
if (gRestrictCommands) {
- Warning("%s: IO freeze restricted command %d\n",
- __FUNCTION__, requestMsg->opCode);
+ g_warning("%s: IO freeze restricted command %d\n",
+ __FUNCTION__, requestMsg->opCode);
err = VIX_E_OBJECT_IS_BUSY;
goto abort;
}
@@ -10236,7 +10482,8 @@ VixTools_ProcessVixCommand(VixCommandRequestHeader *requestMsg, // IN
if (!VixToolsCheckIfVixCommandEnabled(requestMsg->opCode, confDictRef)) {
err = VIX_E_OPERATION_DISABLED;
- Debug("%s: command %d disabled by configuration\n", __FUNCTION__, requestMsg->opCode);
+ g_message("%s: command %d disabled by configuration\n",
+ __FUNCTION__, requestMsg->opCode);
goto abort;
}
@@ -10917,11 +11164,16 @@ VixToolsEnableStaticOnPrimary(const char *ipAddr, // IN
char *
VixToolsEscapeXMLString(const char *str) // IN
{
+ /*
+ * Escape the escape character (%) and the five characters that are XML
+ * sensitive - ', ", &, < and >.
+ */
+
static const int bytesToEscape[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '%'
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // '<' and '>'
+ 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, // ", %, & and '
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // < and >
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -10966,7 +11218,7 @@ VixToolsXMLStringEscapedLen(const char *str, // IN
size_t totalLen = 0;
while (TRUE) {
- size_t nextLen = strcspn(str, "<>%");
+ size_t nextLen = strcspn(str, "%<>&\'\"");
totalLen += nextLen;
if ('\0' == str[nextLen]) {
@@ -11047,7 +11299,6 @@ GuestAuthPasswordAuthenticateImpersonate(
VGAuthError vgErr;
VGAuthUserHandle *newHandle = NULL;
- Debug(">%s\n", __FUNCTION__);
err = VixMsg_DeObfuscateNamePassword(obfuscatedNamePassword,
&username,
&password);
@@ -11087,13 +11338,12 @@ GuestAuthPasswordAuthenticateImpersonate(
#endif
currentUserHandle = newHandle;
+ gImpersonatedUsername = Util_SafeStrdup(username);
err = VIX_OK;
done:
- Debug("<%s\n", __FUNCTION__);
-
return err;
#else
return VIX_E_NOT_SUPPORTED;
@@ -11131,7 +11381,6 @@ GuestAuthSAMLAuthenticateAndImpersonate(
VGAuthError vgErr;
VGAuthUserHandle *newHandle = NULL;
- Debug(">%s\n", __FUNCTION__);
err = VixMsg_DeObfuscateNamePassword(obfuscatedNamePassword,
&token,
&username);
@@ -11174,14 +11423,12 @@ GuestAuthSAMLAuthenticateAndImpersonate(
#endif
currentUserHandle = newHandle;
-
+ gImpersonatedUsername = VixToolsGetImpersonatedUsername(NULL);
err = VIX_OK;
done:
- Debug("<%s\n", __FUNCTION__);
-
return err;
#else
return VIX_E_NOT_SUPPORTED;
@@ -11299,7 +11546,7 @@ QueryVGAuthConfig(GKeyFile *confDictRef) // IN
USE_VGAUTH_DEFAULT);
}
- Debug("%s: vgauth usage is: %d\n", __FUNCTION__, retVal);
+ g_message("%s: vgauth usage is: %d\n", __FUNCTION__, retVal);
return retVal;
}
diff --git a/open-vm-tools/services/plugins/vix/vixToolsInt.h b/open-vm-tools/services/plugins/vix/vixToolsInt.h
index b710a01a..e7739d61 100644
--- a/open-vm-tools/services/plugins/vix/vixToolsInt.h
+++ b/open-vm-tools/services/plugins/vix/vixToolsInt.h
@@ -41,6 +41,8 @@
#endif
+extern char *gImpersonatedUsername;
+#define IMPERSONATED_USERNAME ((gImpersonatedUsername) ? gImpersonatedUsername : "Unset")
typedef struct VixToolsEnvIterator VixToolsEnvIterator;
diff --git a/open-vm-tools/services/plugins/vmbackup/README b/open-vm-tools/services/plugins/vmbackup/README
index 763d658a..eba803c7 100644
--- a/open-vm-tools/services/plugins/vmbackup/README
+++ b/open-vm-tools/services/plugins/vmbackup/README
@@ -4,28 +4,31 @@ This is an attempt to describe the VmBackup state machine using ASCII diagrams.
The main state machine, implemented in stateMachine.c, works as follows:
- -------------> IDLE <-----------|
- | | |
- | b, e | a |
- | | |
- | e \/ |
- SCRIPT_ERROR <--- SCRIPT_FREEZE |
- ^ | |
- | d | b |
- | e \/ | b, e
- SYNC_ERROR <----- SYNC_FREEZE |
- ^ | |
- | | c |
- | e \/ |
- |----------- SYNC_THAW |
- | |
- | d |
- \/ |
- SCRIPT_THAW --------
+ -------------------> IDLE <-----------|
+ | | |
+ | b, e | a |
+ | | |
+ | e \/ |
+ SCRIPT_ERROR <--------- SCRIPT_FREEZE |
+ ^ | b' | |
+ | e \/ | |
+ SYNC_ERROR <-- SYNC_FREEZE_WAIT | |
+ | d | b | b |
+ | e \/ \/ | b, e
+ SYNC_ERROR <----------- SYNC_FREEZE |
+ ^ | |
+ | | c |
+ | e \/ |
+ |------------------ SYNC_THAW |
+ | |
+ | d |
+ \/ |
+ SCRIPT_THAW --------
The transitions mean the following events / conditions:
a. vmbackup.start RPC
+ b'. vmbackup operation is running in background (Linux specific)
b. vmbackup operation is finished
c. vmbackup.snapshotDone RPC
d. sync provider operation is finished
diff --git a/open-vm-tools/services/plugins/vmbackup/nullProvider.c b/open-vm-tools/services/plugins/vmbackup/nullProvider.c
index df34b1aa..60856dd8 100644
--- a/open-vm-tools/services/plugins/vmbackup/nullProvider.c
+++ b/open-vm-tools/services/plugins/vmbackup/nullProvider.c
@@ -31,12 +31,12 @@
#include "vmBackupInt.h"
+#if defined(_WIN32)
/*
******************************************************************************
* VmBackupNullStart -- */ /**
*
- * Calls sync(2) on POSIX systems. Sends the "commit snapshot" event to the
- * host.
+ * Sends the "commit snapshot" event to the host.
*
* @param[in] state Backup state.
* @param[in] clientData Unused.
@@ -50,16 +50,44 @@ static Bool
VmBackupNullStart(VmBackupState *state,
void *clientData)
{
-#if !defined(_WIN32)
+ VmBackup_SetCurrentOp(state, NULL, NULL, __FUNCTION__);
+ return VmBackup_SendEvent(VMBACKUP_EVENT_SNAPSHOT_COMMIT, 0, "");
+}
+
+#else
+
+/*
+ ******************************************************************************
+ * VmBackupNullStart -- */ /**
+ *
+ * Calls sync(2) on POSIX systems. Sends the "commit snapshot" event to the
+ * host.
+ *
+ * @param[in] ctx Plugin context.
+ * @param[in] state Backup state.
+ *
+ ******************************************************************************
+ */
+
+static void
+VmBackupNullStart(ToolsAppCtx *ctx,
+ void *clientData)
+{
+ VmBackupState *state = (VmBackupState*) clientData;
/*
* This is more of a "let's at least do something" than something that
* will actually ensure data integrity...
*/
sync();
-#endif
VmBackup_SetCurrentOp(state, NULL, NULL, __FUNCTION__);
- return VmBackup_SendEvent(VMBACKUP_EVENT_SNAPSHOT_COMMIT, 0, "");
+ if (!VmBackup_SendEvent(VMBACKUP_EVENT_SNAPSHOT_COMMIT, 0, "")) {
+ g_warning("Failed to send commit event to host");
+ state->freezeStatus = VMBACKUP_FREEZE_ERROR;
+ } else {
+ state->freezeStatus = VMBACKUP_FREEZE_FINISHED;
+ }
}
+#endif
/*
diff --git a/open-vm-tools/services/plugins/vmbackup/stateMachine.c b/open-vm-tools/services/plugins/vmbackup/stateMachine.c
index 07215393..071648cc 100644
--- a/open-vm-tools/services/plugins/vmbackup/stateMachine.c
+++ b/open-vm-tools/services/plugins/vmbackup/stateMachine.c
@@ -44,6 +44,9 @@
#include "util.h"
#include "vmBackupSignals.h"
#include "guestQuiesce.h"
+#if !defined(_WIN32)
+#include "vmware/tools/threadPool.h"
+#endif
#include "vmware/tools/utils.h"
#include "vmware/tools/vmbackup.h"
#include "xdrutil.h"
@@ -76,6 +79,9 @@ static VmBackupState *gBackupState = NULL;
static Bool
VmBackupEnableSync(void);
+static Bool
+VmBackupEnableSyncWait(void);
+
/**
* Returns a string representation of the given state machine state.
@@ -95,6 +101,9 @@ VmBackupGetStateName(VmBackupMState state)
case VMBACKUP_MSTATE_SCRIPT_FREEZE:
return "SCRIPT_FREEZE";
+ case VMBACKUP_MSTATE_SYNC_FREEZE_WAIT:
+ return "SYNC_FREEZE_WAIT";
+
case VMBACKUP_MSTATE_SYNC_FREEZE:
return "SYNC_FREEZE";
@@ -269,10 +278,13 @@ VmBackupFinalize(void)
g_source_destroy(gBackupState->abortTimer);
g_source_unref(gBackupState->abortTimer);
}
+
+ g_static_mutex_lock(&gBackupState->opLock);
if (gBackupState->currentOp != NULL) {
VmBackup_Cancel(gBackupState->currentOp);
VmBackup_Release(gBackupState->currentOp);
}
+ g_static_mutex_unlock(&gBackupState->opLock);
VmBackup_SendEvent(VMBACKUP_EVENT_REQUESTOR_DONE, VMBACKUP_SUCCESS, "");
@@ -287,6 +299,7 @@ VmBackupFinalize(void)
}
gBackupState->provider->release(gBackupState->provider);
+ g_static_mutex_free(&gBackupState->opLock);
g_free(gBackupState->scriptArg);
g_free(gBackupState->volumes);
g_free(gBackupState->snapshots);
@@ -367,6 +380,7 @@ VmBackupOnError(void)
}
break;
+ case VMBACKUP_MSTATE_SYNC_FREEZE_WAIT:
case VMBACKUP_MSTATE_SYNC_FREEZE:
case VMBACKUP_MSTATE_SYNC_THAW:
/* Next state is "sync error". */
@@ -404,11 +418,13 @@ VmBackupDoAbort(void)
if (gBackupState->machineState != VMBACKUP_MSTATE_SCRIPT_ERROR &&
gBackupState->machineState != VMBACKUP_MSTATE_SYNC_ERROR) {
/* Mark the current operation as cancelled. */
+ g_static_mutex_lock(&gBackupState->opLock);
if (gBackupState->currentOp != NULL) {
VmBackup_Cancel(gBackupState->currentOp);
VmBackup_Release(gBackupState->currentOp);
gBackupState->currentOp = NULL;
}
+ g_static_mutex_unlock(&gBackupState->opLock);
VmBackup_SendEvent(VMBACKUP_EVENT_REQUESTOR_ABORT,
VMBACKUP_REMOTE_ABORT,
@@ -462,27 +478,32 @@ VmBackupAsyncCallback(void *clientData)
g_source_unref(gBackupState->timerEvent);
gBackupState->timerEvent = NULL;
+ g_static_mutex_lock(&gBackupState->opLock);
if (gBackupState->currentOp != NULL) {
g_debug("VmBackupAsyncCallback: checking %s\n", gBackupState->currentOpName);
status = VmBackup_QueryStatus(gBackupState->currentOp);
}
+ g_static_mutex_unlock(&gBackupState->opLock);
switch (status) {
case VMBACKUP_STATUS_PENDING:
goto exit;
case VMBACKUP_STATUS_FINISHED:
+ g_static_mutex_lock(&gBackupState->opLock);
if (gBackupState->currentOpName != NULL) {
g_debug("Async request '%s' completed\n", gBackupState->currentOpName);
VmBackup_Release(gBackupState->currentOp);
gBackupState->currentOpName = NULL;
}
gBackupState->currentOp = NULL;
+ g_static_mutex_unlock(&gBackupState->opLock);
break;
default:
{
gchar *msg;
+ g_static_mutex_lock(&gBackupState->opLock);
if (gBackupState->errorMsg != NULL) {
msg = g_strdup_printf("'%s' operation failed: %s",
gBackupState->currentOpName,
@@ -498,6 +519,7 @@ VmBackupAsyncCallback(void *clientData)
VmBackup_Release(gBackupState->currentOp);
gBackupState->currentOp = NULL;
+ g_static_mutex_unlock(&gBackupState->opLock);
VmBackupOnError();
goto exit;
}
@@ -512,9 +534,12 @@ VmBackupAsyncCallback(void *clientData)
gBackupState->callback = NULL;
if (cb(gBackupState)) {
+ g_static_mutex_lock(&gBackupState->opLock);
if (gBackupState->currentOp != NULL || gBackupState->forceRequeue) {
+ g_static_mutex_unlock(&gBackupState->opLock);
goto exit;
}
+ g_static_mutex_unlock(&gBackupState->opLock);
} else {
VmBackupOnError();
goto exit;
@@ -527,6 +552,13 @@ VmBackupAsyncCallback(void *clientData)
*/
switch (gBackupState->machineState) {
case VMBACKUP_MSTATE_SCRIPT_FREEZE:
+ /* Next state is "sync freeze wait". */
+ if (!VmBackupEnableSyncWait()) {
+ VmBackupOnError();
+ }
+ break;
+
+ case VMBACKUP_MSTATE_SYNC_FREEZE_WAIT:
/* Next state is "sync freeze". */
if (!VmBackupEnableSync()) {
VmBackupOnError();
@@ -582,23 +614,44 @@ exit:
/**
- * Calls the sync provider's start function.
+ * Calls the sync provider's start function and moves the state
+ * machine to next state.
*
- * @param[in] state The backup state.
+ * For Windows next state is VMBACKUP_MSTATE_SYNC_FREEZE, whereas
+ * next state is VMBACKUP_MSTATE_SYNC_FREEZE_WAIT for Linux. Details
+ * below.
*
* @return Whether the provider's start callback was successful.
*/
static Bool
-VmBackupEnableSync(void)
+VmBackupEnableSyncWait(void)
{
g_debug("*** %s\n", __FUNCTION__);
g_signal_emit_by_name(gBackupState->ctx->serviceObj,
TOOLS_CORE_SIG_IO_FREEZE,
gBackupState->ctx,
TRUE);
+#if defined(_WIN32)
+ gBackupState->freezeStatus = VMBACKUP_FREEZE_FINISHED;
if (!gBackupState->provider->start(gBackupState,
gBackupState->provider->clientData)) {
+#else
+ /*
+ * PR 1020224:
+ * For Linux, FIFREEZE could take really long at times,
+ * especially when guest is running IO load. We have also
+ * seen slowness in performing open() on NFS mount points.
+ * So, we need to run freeze operation in a separate thread
+ * and track it with an extra state in the state machine.
+ */
+ gBackupState->freezeStatus = VMBACKUP_FREEZE_PENDING;
+ if (!ToolsCorePool_SubmitTask(gBackupState->ctx,
+ gBackupState->provider->start,
+ gBackupState,
+ NULL)) {
+ g_warning("Failed to submit backup start task.");
+#endif
g_signal_emit_by_name(gBackupState->ctx->serviceObj,
TOOLS_CORE_SIG_IO_FREEZE,
gBackupState->ctx,
@@ -609,7 +662,48 @@ VmBackupEnableSync(void)
return FALSE;
}
+#if defined(_WIN32)
+ /* Move to next state */
gBackupState->machineState = VMBACKUP_MSTATE_SYNC_FREEZE;
+#else
+ g_debug("Submitted backup start task.");
+ /* Move to next state */
+ gBackupState->machineState = VMBACKUP_MSTATE_SYNC_FREEZE_WAIT;
+#endif
+
+ return TRUE;
+}
+
+
+/**
+ * After sync provider's start function returns and moves the state
+ * machine to VMBACKUP_MSTATE_SYNC_FREEZE state.
+ *
+ * @return Whether the provider's start callback was successful.
+ */
+
+static Bool
+VmBackupEnableSync(void)
+{
+ g_debug("*** %s\n", __FUNCTION__);
+ if (gBackupState->freezeStatus == VMBACKUP_FREEZE_ERROR) {
+ g_signal_emit_by_name(gBackupState->ctx->serviceObj,
+ TOOLS_CORE_SIG_IO_FREEZE,
+ gBackupState->ctx,
+ FALSE);
+ VmBackup_SendEvent(VMBACKUP_EVENT_REQUESTOR_ERROR,
+ VMBACKUP_SYNC_ERROR,
+ "Error when enabling the sync provider.");
+ return FALSE;
+
+ } else if (gBackupState->freezeStatus == VMBACKUP_FREEZE_CANCELED ||
+ gBackupState->freezeStatus == VMBACKUP_FREEZE_FINISHED) {
+ /* Move to next state */
+ gBackupState->machineState = VMBACKUP_MSTATE_SYNC_FREEZE;
+ } else {
+ ASSERT(gBackupState->freezeStatus == VMBACKUP_FREEZE_PENDING);
+ }
+
return TRUE;
}
@@ -726,8 +820,10 @@ VmBackupStartCommon(RpcInData *data,
gBackupState->ctx = data->appCtx;
gBackupState->pollPeriod = 1000;
gBackupState->machineState = VMBACKUP_MSTATE_IDLE;
+ gBackupState->freezeStatus = VMBACKUP_FREEZE_FINISHED;
gBackupState->provider = provider;
gBackupState->needsPriv = FALSE;
+ g_static_mutex_init(&gBackupState->opLock);
gBackupState->enableNullDriver = VmBackupConfigGetBoolean(ctx->config,
"enableNullDriver",
TRUE);
diff --git a/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c b/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c
index 387e8395..11d37843 100644
--- a/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c
+++ b/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c
@@ -61,10 +61,10 @@ typedef struct VmBackupDriverOp {
*/
static Bool
-VmBackupDriverThaw(SyncDriverHandle *handle)
+VmBackupDriverThaw(VmBackupDriverOp *op)
{
- Bool success = SyncDriver_Thaw(*handle);
- SyncDriver_CloseHandle(handle);
+ Bool success = SyncDriver_Thaw(*op->syncHandle);
+ SyncDriver_CloseHandle(op->syncHandle);
return success;
}
@@ -106,7 +106,7 @@ VmBackupDriverOpQuery(VmBackupOp *_op) // IN
case SYNCDRIVER_IDLE:
if (op->canceled) {
- VmBackupDriverThaw(op->syncHandle);
+ VmBackupDriverThaw(op);
}
/*
* This prevents the release callback from freeing the handle, which
@@ -117,7 +117,7 @@ VmBackupDriverOpQuery(VmBackupOp *_op) // IN
break;
default:
- VmBackupDriverThaw(op->syncHandle);
+ VmBackupDriverThaw(op);
ret = VMBACKUP_STATUS_ERROR;
break;
}
@@ -149,7 +149,7 @@ static void
VmBackupDriverOpRelease(VmBackupOp *_op) // IN
{
VmBackupDriverOp *op = (VmBackupDriverOp *) _op;
- free(op->syncHandle);
+ g_free(op->syncHandle);
free(op);
}
@@ -231,10 +231,11 @@ VmBackupNewDriverOp(VmBackupState *state, // IN
state->enableNullDriver : FALSE,
op->syncHandle);
} else {
- success = VmBackupDriverThaw(op->syncHandle);
+ success = VmBackupDriverThaw(op);
}
if (!success) {
g_warning("Error %s filesystems.", freeze ? "freezing" : "thawing");
+ g_free(op->syncHandle);
free(op);
op = NULL;
}
@@ -263,33 +264,29 @@ VmBackupNewDriverOp(VmBackupState *state, // IN
static Bool
VmBackupSyncDriverReadyForSnapshot(VmBackupState *state)
{
+ Bool success;
SyncDriverHandle *handle = state->clientData;
g_debug("*** %s\n", __FUNCTION__);
if (handle != NULL && *handle != SYNCDRIVER_INVALID_HANDLE) {
- Bool success;
success = VmBackup_SendEvent(VMBACKUP_EVENT_SNAPSHOT_COMMIT, 0, "");
- if (!success) {
- /*
- * If the vmx does not know this event (e.g. due to an RPC timeout),
- * then filesystems need to be thawed here because snapshotDone
- * will not be sent by the vmx.
- */
- g_debug("Thawing filesystems.");
- if (!VmBackupDriverThaw(handle)) {
- g_warning("Error thawing filesystems.");
- }
+ if (success) {
+ state->freezeStatus = VMBACKUP_FREEZE_FINISHED;
+ } else {
+ state->freezeStatus = VMBACKUP_FREEZE_ERROR;
}
-
return success;
}
+
+ /* op failed */
+ state->freezeStatus = VMBACKUP_FREEZE_ERROR;
return TRUE;
}
/* Sync provider implementation. */
-
+#if defined(_WIN32)
/*
*-----------------------------------------------------------------------------
*
@@ -362,6 +359,83 @@ VmBackupSyncDriverOnlyStart(VmBackupState *state,
__FUNCTION__);
}
+#else
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VmBackupSyncDriverStart --
+ *
+ * Starts an asynchronous operation to enable the sync driver.
+ *
+ * Result
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+VmBackupSyncDriverStart(ToolsAppCtx *ctx,
+ void *clientData)
+{
+ VmBackupDriverOp *op;
+ VmBackupState *state = (VmBackupState*) clientData;
+
+ g_debug("*** %s\n", __FUNCTION__);
+ op = VmBackupNewDriverOp(state, TRUE, NULL, state->volumes, TRUE);
+
+ if (op != NULL) {
+ state->clientData = op->syncHandle;
+ }
+
+ VmBackup_SetCurrentOp(state,
+ (VmBackupOp *) op,
+ VmBackupSyncDriverReadyForSnapshot,
+ __FUNCTION__);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VmBackupSyncDriverOnlyStart --
+ *
+ * Starts an asynchronous operation to enable the sync driver without using
+ * NullDriver fallback.
+ *
+ * Result
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+VmBackupSyncDriverOnlyStart(ToolsAppCtx *ctx,
+ void *clientData)
+{
+ VmBackupDriverOp *op;
+ VmBackupState *state = (VmBackupState*) clientData;
+
+ g_debug("*** %s\n", __FUNCTION__);
+ op = VmBackupNewDriverOp(state, TRUE, NULL, state->volumes, FALSE);
+
+ if (op != NULL) {
+ state->clientData = op->syncHandle;
+ }
+
+ VmBackup_SetCurrentOp(state,
+ (VmBackupOp *) op,
+ VmBackupSyncDriverReadyForSnapshot,
+ __FUNCTION__);
+}
+#endif
+
/*
*-----------------------------------------------------------------------------
diff --git a/open-vm-tools/services/plugins/vmbackup/vmBackupInt.h b/open-vm-tools/services/plugins/vmbackup/vmBackupInt.h
index 1334b85a..04e866ca 100644
--- a/open-vm-tools/services/plugins/vmbackup/vmBackupInt.h
+++ b/open-vm-tools/services/plugins/vmbackup/vmBackupInt.h
@@ -31,6 +31,9 @@
#include "vmware.h"
#include "vmware/guestrpc/vmbackup.h"
#include "vmware/tools/plugin.h"
+#if !defined(_WIN32)
+#include "vmware/tools/threadPool.h"
+#endif
typedef enum {
VMBACKUP_STATUS_PENDING,
@@ -40,6 +43,13 @@ typedef enum {
} VmBackupOpStatus;
typedef enum {
+ VMBACKUP_FREEZE_PENDING,
+ VMBACKUP_FREEZE_FINISHED,
+ VMBACKUP_FREEZE_CANCELED,
+ VMBACKUP_FREEZE_ERROR
+} VmBackupFreezeStatus;
+
+typedef enum {
VMBACKUP_SCRIPT_FREEZE,
VMBACKUP_SCRIPT_FREEZE_FAIL,
VMBACKUP_SCRIPT_THAW
@@ -48,6 +58,7 @@ typedef enum {
typedef enum {
VMBACKUP_MSTATE_IDLE,
VMBACKUP_MSTATE_SCRIPT_FREEZE,
+ VMBACKUP_MSTATE_SYNC_FREEZE_WAIT,
VMBACKUP_MSTATE_SYNC_FREEZE,
VMBACKUP_MSTATE_SYNC_THAW,
VMBACKUP_MSTATE_SCRIPT_THAW,
@@ -75,12 +86,19 @@ struct VmBackupSyncProvider;
* Holds information about the current state of the backup operation.
* Don't modify the fields directly - rather, use VmBackup_SetCurrentOp,
* which does most of the handling needed by users of the state machine.
+ *
+ * NOTE: The thread for freeze operation modifies currentOp in BackupState
+ * which is also accessed by the AsyncCallback driving the state
+ * machine (run by main thread). Also, gcc might generate two
+ * instructions for writing a 64-bit value. Therefore, protect the
+ * access to currentOp and related fields using opLock mutex.
*/
typedef struct VmBackupState {
ToolsAppCtx *ctx;
VmBackupOp *currentOp;
const char *currentOpName;
+ GStaticMutex opLock; // See note above
char *volumes;
char *snapshots;
guint pollPeriod;
@@ -104,6 +122,7 @@ typedef struct VmBackupState {
ssize_t currentScript;
gchar *errorMsg;
VmBackupMState machineState;
+ VmBackupFreezeStatus freezeStatus;
struct VmBackupSyncProvider *provider;
} VmBackupState;
@@ -118,7 +137,11 @@ typedef Bool (*VmBackupProviderCallback)(VmBackupState *, void *clientData);
*/
typedef struct VmBackupSyncProvider {
+#if defined(_WIN32)
VmBackupProviderCallback start;
+#else
+ ToolsCorePoolCb start;
+#endif
VmBackupProviderCallback snapshotDone;
void (*release)(struct VmBackupSyncProvider *);
void *clientData;
@@ -147,10 +170,16 @@ VmBackup_SetCurrentOp(VmBackupState *state,
ASSERT(state != NULL);
ASSERT(state->currentOp == NULL);
ASSERT(currentOpName != NULL);
+
+ g_static_mutex_lock(&state->opLock);
+
state->currentOp = op;
state->callback = callback;
state->currentOpName = currentOpName;
- state->forceRequeue = (callback != NULL && state->currentOp == NULL);
+ state->forceRequeue = (callback != NULL && op == NULL);
+
+ g_static_mutex_unlock(&state->opLock);
+
return (op != NULL);
}
diff --git a/open-vm-tools/services/vmtoolsd/cmdLine.c b/open-vm-tools/services/vmtoolsd/cmdLine.c
index f87cbf2b..c0a64cb5 100644
--- a/open-vm-tools/services/vmtoolsd/cmdLine.c
+++ b/open-vm-tools/services/vmtoolsd/cmdLine.c
@@ -326,14 +326,14 @@ ToolsCore_ParseCommandLine(ToolsServiceState *state,
g_printerr("%s is an invalid container name.\n", state->name);
goto exit;
}
- state->mainService = (strcmp(state->name, VMTOOLS_GUEST_SERVICE) == 0);
+ state->mainService = TOOLS_IS_MAIN_SERVICE(state);
}
/* Configure logging system. */
ToolsCore_ReloadConfig(state, TRUE);
/* Log the commandline for debugging purposes. */
- g_debug("CmdLine: \"%s\"\n", cmdStr);
+ g_info("CmdLine: \"%s\"\n", cmdStr);
#if defined(G_PLATFORM_WIN32)
if (kill) {
@@ -344,7 +344,7 @@ ToolsCore_ParseCommandLine(ToolsServiceState *state,
}
#else
/* If not running the "vmusr" service, ignore the blockFd parameter. */
- if (strcmp(state->name, VMTOOLS_USER_SERVICE) != 0) {
+ if (!TOOLS_IS_USER_SERVICE(state)) {
if (state->ctx.blockFD >= 0) {
close(state->ctx.blockFD);
}
diff --git a/open-vm-tools/services/vmtoolsd/l10n/de.vmsg b/open-vm-tools/services/vmtoolsd/l10n/de.vmsg
index aabd9dcb..a4f85269 100644
--- a/open-vm-tools/services/vmtoolsd/l10n/de.vmsg
+++ b/open-vm-tools/services/vmtoolsd/l10n/de.vmsg
@@ -1,5 +1,5 @@
##########################################################
-# Copyright (C) 2010-2015 VMware, Inc. All rights reserved.
+# Copyright (C) 2010 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
diff --git a/open-vm-tools/services/vmtoolsd/l10n/ja.vmsg b/open-vm-tools/services/vmtoolsd/l10n/ja.vmsg
index c63bb095..d36ba314 100644
--- a/open-vm-tools/services/vmtoolsd/l10n/ja.vmsg
+++ b/open-vm-tools/services/vmtoolsd/l10n/ja.vmsg
@@ -1,5 +1,5 @@
##########################################################
-# Copyright (C) 2010-2015 VMware, Inc. All rights reserved.
+# Copyright (C) 2010 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
diff --git a/open-vm-tools/services/vmtoolsd/l10n/ko.vmsg b/open-vm-tools/services/vmtoolsd/l10n/ko.vmsg
index f6b8b178..8a81fded 100644
--- a/open-vm-tools/services/vmtoolsd/l10n/ko.vmsg
+++ b/open-vm-tools/services/vmtoolsd/l10n/ko.vmsg
@@ -1,5 +1,5 @@
##########################################################
-# Copyright (C) 2010-2015 VMware, Inc. All rights reserved.
+# Copyright (C) 2010 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
diff --git a/open-vm-tools/services/vmtoolsd/mainLoop.c b/open-vm-tools/services/vmtoolsd/mainLoop.c
index ba2c0aa3..f773cff1 100644
--- a/open-vm-tools/services/vmtoolsd/mainLoop.c
+++ b/open-vm-tools/services/vmtoolsd/mainLoop.c
@@ -160,8 +160,10 @@ ToolsCoreIOFreezeCb(gpointer src,
if (state->configCheckTask > 0 && freeze) {
g_source_remove(state->configCheckTask);
state->configCheckTask = 0;
+ VMTools_SuspendLogIO();
} else if (state->configCheckTask == 0 && !freeze) {
- state->configCheckTask = g_timeout_add(CONF_POLL_TIME * 10,
+ VMTools_ResumeLogIO();
+ state->configCheckTask = g_timeout_add(CONF_POLL_TIME * 1000,
ToolsCoreConfFileCb,
state);
}
@@ -229,7 +231,7 @@ ToolsCoreRunLoop(ToolsServiceState *state)
state);
}
- state->configCheckTask = g_timeout_add(CONF_POLL_TIME * 10,
+ state->configCheckTask = g_timeout_add(CONF_POLL_TIME * 1000,
ToolsCoreConfFileCb,
state);
@@ -314,7 +316,7 @@ ToolsCore_GetTcloName(ToolsServiceState *state)
{
if (state->mainService) {
return TOOLS_DAEMON_NAME;
- } else if (strcmp(state->name, VMTOOLS_USER_SERVICE) == 0) {
+ } else if (TOOLS_IS_USER_SERVICE(state)) {
return TOOLS_DND_NAME;
} else {
return NULL;
diff --git a/open-vm-tools/services/vmtoolsd/mainPosix.c b/open-vm-tools/services/vmtoolsd/mainPosix.c
index 019035b3..af01a494 100644
--- a/open-vm-tools/services/vmtoolsd/mainPosix.c
+++ b/open-vm-tools/services/vmtoolsd/mainPosix.c
@@ -104,7 +104,7 @@ ToolsCoreSigUsrHandler(const siginfo_t *info,
ToolsCore_DumpState(&gState);
g_info("Shutting down guestrpc on signal USR1 ...\n");
- if (strcmp(gState.ctx.name, VMTOOLS_USER_SERVICE) == 0) {
+ if (TOOLS_IS_USER_SERVICE(&gState.ctx)) {
RpcChannel_Shutdown(gState.ctx.rpc);
gState.ctx.rpc = NULL;
}
diff --git a/open-vm-tools/services/vmtoolsd/pluginMgr.c b/open-vm-tools/services/vmtoolsd/pluginMgr.c
index 2f52387b..700f23fe 100644
--- a/open-vm-tools/services/vmtoolsd/pluginMgr.c
+++ b/open-vm-tools/services/vmtoolsd/pluginMgr.c
@@ -740,7 +740,7 @@ ToolsCore_LoadPlugins(ToolsServiceState *state)
g_module_make_resident(plugin->module);
g_ptr_array_add(state->plugins, plugin);
VMTools_BindTextDomain(plugin->data->name, NULL, NULL);
- g_debug("Plugin '%s' initialized.\n", plugin->data->name);
+ g_message("Plugin '%s' initialized.\n", plugin->data->name);
}
}
@@ -918,7 +918,7 @@ ToolsCore_UnloadPlugins(ToolsServiceState *state)
ToolsPlugin *plugin = g_ptr_array_index(state->plugins, state->plugins->len - 1);
GArray *regs = (plugin->data != NULL) ? plugin->data->regs : NULL;
- g_debug("Unloading plugin '%s'.\n", plugin->data->name);
+ g_message("Unloading plugin '%s'.\n", plugin->data->name);
if (regs != NULL) {
guint i;
diff --git a/open-vm-tools/services/vmtoolsd/toolsRpc.c b/open-vm-tools/services/vmtoolsd/toolsRpc.c
index ed3db564..94144764 100644
--- a/open-vm-tools/services/vmtoolsd/toolsRpc.c
+++ b/open-vm-tools/services/vmtoolsd/toolsRpc.c
@@ -27,6 +27,9 @@
#include <stdlib.h>
#include <string.h>
+#if !defined(_WIN32)
+#include <unistd.h>
+#endif
#include "vm_basic_defs.h"
#include "vm_assert.h"
#include "conf.h"
@@ -35,6 +38,7 @@
#include "toolsCoreInt.h"
#include "vm_tools_version.h"
#include "vmware/tools/utils.h"
+#include "vmware/tools/log.h"
#include "vm_version.h"
/**
@@ -124,7 +128,7 @@ ToolsCoreRpcCapReg(RpcInData *data)
/* Tell the host the location of the conf directory. */
msg = g_strdup_printf("tools.capability.guest_conf_directory %s", confPath);
if (!RpcChannel_Send(state->ctx.rpc, msg, strlen(msg) + 1, NULL, NULL)) {
- g_debug("Unable to register guest conf directory capability.\n");
+ g_warning("Unable to register guest conf directory capability.\n");
}
g_free(msg);
msg = NULL;
@@ -132,27 +136,58 @@ ToolsCoreRpcCapReg(RpcInData *data)
/* Send the tools version to the VMX. */
if (state->mainService) {
uint32 version;
+ uint32 type = TOOLS_TYPE_UNKNOWN;
char *result = NULL;
size_t resultLen;
gchar *toolsVersion;
+ gboolean disableVersion = g_key_file_get_boolean(state->ctx.config,
+ "vmtools",
+ CONFNAME_DISABLETOOLSVERSION,
+ NULL);
+#if defined(_WIN32)
+ type = TOOLS_TYPE_MSI;
+#else
#if defined(OPEN_VM_TOOLS)
- version = TOOLS_VERSION_UNMANAGED;
+ type = TOOLS_TYPE_OVT;
#else
- gboolean disableVersion;
+ {
+ static int is_osp = -1;
- disableVersion = g_key_file_get_boolean(state->ctx.config,
- "vmtools",
- CONFNAME_DISABLETOOLSVERSION,
- NULL);
- version = disableVersion ? TOOLS_VERSION_UNMANAGED : TOOLS_VERSION_CURRENT;
+ if (is_osp == -1) {
+ is_osp = (access("/usr/lib/vmware-tools/dsp", F_OK) == 0);
+ }
+ type = is_osp ? TOOLS_TYPE_OSP : TOOLS_TYPE_TARBALL;
+ }
+#endif
#endif
- toolsVersion = g_strdup_printf("tools.set.version %u", version);
+ version = disableVersion ? TOOLS_VERSION_UNMANAGED : TOOLS_VERSION_CURRENT;
+
+ /*
+ * First try "tools.set.versiontype", if that fails because host is too
+ * old, fall back to "tools.set.version."
+ */
+ toolsVersion = g_strdup_printf("tools.set.versiontype %u %u", version, type);
if (!RpcChannel_Send(state->ctx.rpc, toolsVersion, strlen(toolsVersion) + 1,
&result, &resultLen)) {
- g_debug("Error setting tools version: %s.\n", result);
+ vm_free(result);
+ g_free(toolsVersion);
+
+ /*
+ * Fall back to old behavior for OSPs and OVT so that tools will be
+ * reported as guest managed.
+ */
+ if (type == TOOLS_TYPE_OSP || type == TOOLS_TYPE_OVT) {
+ version = TOOLS_VERSION_UNMANAGED;
+ }
+ toolsVersion = g_strdup_printf("tools.set.version %u", version);
+
+ if (!RpcChannel_Send(state->ctx.rpc, toolsVersion, strlen(toolsVersion) + 1,
+ &result, &resultLen)) {
+ g_warning("Error setting tools version: %s.\n", result);
+ }
}
vm_free(result);
g_free(toolsVersion);
@@ -247,8 +282,8 @@ ToolsCore_InitRpc(ToolsServiceState *state)
* XXX: this should be relaxed when we try to bring up a VMCI or TCP channel.
*/
if (!state->ctx.isVMware) {
- g_debug("The %s service needs to run inside a virtual machine.\n",
- state->name);
+ g_info("The %s service needs to run inside a virtual machine.\n",
+ state->name);
state->ctx.rpc = NULL;
} else {
state->ctx.rpc = RpcChannel_New();
diff --git a/open-vm-tools/toolbox/Makefile.am b/open-vm-tools/toolbox/Makefile.am
index c0c6313f..5733c573 100644
--- a/open-vm-tools/toolbox/Makefile.am
+++ b/open-vm-tools/toolbox/Makefile.am
@@ -27,6 +27,7 @@ vmware_toolbox_cmd_CPPFLAGS += @VMTOOLS_CPPFLAGS@
vmware_toolbox_cmd_SOURCES =
vmware_toolbox_cmd_SOURCES += toolbox-cmd.c
vmware_toolbox_cmd_SOURCES += toolboxcmd-devices.c
+vmware_toolbox_cmd_SOURCES += toolboxcmd-logging.c
vmware_toolbox_cmd_SOURCES += toolboxcmd-scripts.c
vmware_toolbox_cmd_SOURCES += toolboxcmd-shrink.c
vmware_toolbox_cmd_SOURCES += toolboxcmd-stat.c
diff --git a/open-vm-tools/toolbox/Makefile.in b/open-vm-tools/toolbox/Makefile.in
index 4be188cc..06944778 100644
--- a/open-vm-tools/toolbox/Makefile.in
+++ b/open-vm-tools/toolbox/Makefile.in
@@ -68,6 +68,7 @@ PROGRAMS = $(bin_PROGRAMS)
am_vmware_toolbox_cmd_OBJECTS = \
vmware_toolbox_cmd-toolbox-cmd.$(OBJEXT) \
vmware_toolbox_cmd-toolboxcmd-devices.$(OBJEXT) \
+ vmware_toolbox_cmd-toolboxcmd-logging.$(OBJEXT) \
vmware_toolbox_cmd-toolboxcmd-scripts.$(OBJEXT) \
vmware_toolbox_cmd-toolboxcmd-shrink.$(OBJEXT) \
vmware_toolbox_cmd-toolboxcmd-stat.$(OBJEXT) \
@@ -285,8 +286,8 @@ vmware_toolbox_cmd_LDADD = ../libguestlib/libguestlib.la \
@VMTOOLS_LIBS@ $(am__append_1)
vmware_toolbox_cmd_CPPFLAGS = @VMTOOLS_CPPFLAGS@
vmware_toolbox_cmd_SOURCES = toolbox-cmd.c toolboxcmd-devices.c \
- toolboxcmd-scripts.c toolboxcmd-shrink.c toolboxcmd-stat.c \
- toolboxcmd-time.c
+ toolboxcmd-logging.c toolboxcmd-scripts.c toolboxcmd-shrink.c \
+ toolboxcmd-stat.c toolboxcmd-time.c
@HAVE_ICU_FALSE@vmware_toolbox_cmd_LINK = $(LINK)
@HAVE_ICU_TRUE@vmware_toolbox_cmd_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
@HAVE_ICU_TRUE@ $(LIBTOOLFLAGS) --mode=link $(CXX) \
@@ -366,6 +367,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_toolbox_cmd-toolbox-cmd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-devices.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-logging.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-scripts.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-shrink.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-stat.Po@am__quote@
@@ -420,6 +422,20 @@ vmware_toolbox_cmd-toolboxcmd-devices.obj: toolboxcmd-devices.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vmware_toolbox_cmd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vmware_toolbox_cmd-toolboxcmd-devices.obj `if test -f 'toolboxcmd-devices.c'; then $(CYGPATH_W) 'toolboxcmd-devices.c'; else $(CYGPATH_W) '$(srcdir)/toolboxcmd-devices.c'; fi`
+vmware_toolbox_cmd-toolboxcmd-logging.o: toolboxcmd-logging.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vmware_toolbox_cmd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vmware_toolbox_cmd-toolboxcmd-logging.o -MD -MP -MF $(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-logging.Tpo -c -o vmware_toolbox_cmd-toolboxcmd-logging.o `test -f 'toolboxcmd-logging.c' || echo '$(srcdir)/'`toolboxcmd-logging.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-logging.Tpo $(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-logging.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='toolboxcmd-logging.c' object='vmware_toolbox_cmd-toolboxcmd-logging.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vmware_toolbox_cmd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vmware_toolbox_cmd-toolboxcmd-logging.o `test -f 'toolboxcmd-logging.c' || echo '$(srcdir)/'`toolboxcmd-logging.c
+
+vmware_toolbox_cmd-toolboxcmd-logging.obj: toolboxcmd-logging.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vmware_toolbox_cmd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vmware_toolbox_cmd-toolboxcmd-logging.obj -MD -MP -MF $(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-logging.Tpo -c -o vmware_toolbox_cmd-toolboxcmd-logging.obj `if test -f 'toolboxcmd-logging.c'; then $(CYGPATH_W) 'toolboxcmd-logging.c'; else $(CYGPATH_W) '$(srcdir)/toolboxcmd-logging.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-logging.Tpo $(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-logging.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='toolboxcmd-logging.c' object='vmware_toolbox_cmd-toolboxcmd-logging.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vmware_toolbox_cmd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vmware_toolbox_cmd-toolboxcmd-logging.obj `if test -f 'toolboxcmd-logging.c'; then $(CYGPATH_W) 'toolboxcmd-logging.c'; else $(CYGPATH_W) '$(srcdir)/toolboxcmd-logging.c'; fi`
+
vmware_toolbox_cmd-toolboxcmd-scripts.o: toolboxcmd-scripts.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vmware_toolbox_cmd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vmware_toolbox_cmd-toolboxcmd-scripts.o -MD -MP -MF $(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-scripts.Tpo -c -o vmware_toolbox_cmd-toolboxcmd-scripts.o `test -f 'toolboxcmd-scripts.c' || echo '$(srcdir)/'`toolboxcmd-scripts.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-scripts.Tpo $(DEPDIR)/vmware_toolbox_cmd-toolboxcmd-scripts.Po
diff --git a/open-vm-tools/toolbox/l10n/de.vmsg b/open-vm-tools/toolbox/l10n/de.vmsg
index ecaea39b..1546fbaf 100644
--- a/open-vm-tools/toolbox/l10n/de.vmsg
+++ b/open-vm-tools/toolbox/l10n/de.vmsg
@@ -1,5 +1,5 @@
##########################################################
-# Copyright (C) 2010-2015 VMware, Inc. All rights reserved.
+# Copyright (C) 2010 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
@@ -20,6 +20,12 @@ arg.command = "Befehl"
arg.devicename = "Gerätename"
+arg.logging.level = "Ebene der Protokollierung"
+
+arg.logging.service = "Dienstname der Protokollierung"
+
+arg.logging.subcommand = "Vorgang der Protokollierung"
+
arg.mountpoint = "Mount-Punkt"
arg.scriptpath = "Skriptpfad"
@@ -38,7 +44,7 @@ disk.shrink.canceled = "Vorgang zum Verkleinern der Festplatte abgebrochen.\n"
disk.shrink.complete = "Vorgang zum Verkleinern der Festplatte abgeschlossen.\n"
-disk.shrink.conflict = "Die Toolbox betrachten die Festplattenverkleinerung als aktiviert, während der Host die Funktion als deaktiviert betrachtet.\n\n Schließen Sie die Toolbox, und öffnen Sie sie erneut, um eine Synchronisierung mit dem Host vorzunehmen.\n"
+disk.shrink.conflict = "Fehler: Die Toolbox betrachtet die Festplattenverkleinerung als aktiviert, während der Host die Funktion als deaktiviert behandelt.\n\n Schließen Sie die Toolbox und öffnen Sie sie erneut, um eine Synchronisierung mit dem Host vorzunehmen.\n"
disk.shrink.disabled = "Das Verkleinern von Festplatten ist für diese virtuelle Maschine deaktiviert.\n\nDie Verkleinerung ist für verknüpfte Klone, übergeordnete Elemente verknüpfter Klone, \nFestplatten mit vorab zugewiesenem Speicherplatz, Snapshots oder aufgrund weiterer Faktoren deaktiviert. \nWeitere Informationen finden Sie im Benutzerhandbuch.\n"
@@ -52,7 +58,7 @@ disk.shrink.partition.notfound = "Die Partition %1$s wurde nicht gefunden\n"
disk.shrink.partition.unsupported = "Die Partition %1$s kann nicht verkleinert werden\n"
-disk.shrink.unavailable = "Die Verkleinerungsfunktion ist nicht verfügbar.\n\nSie führen entweder eine alte Version eines VMware-Produkts aus, oder es sind zu viele Kommunikationskanäle geöffnet.\n\nWenn Sie eine alte Version eines VMware-Produkts ausführen, sollten Sie ein Upgrade in Erwägung ziehen.\n\nWenn zu viele Kommunikationskanäle geöffnet sind, sollten Sie Ihre virtuelle Maschine aus- und anschließend wieder einschalten.\n"
+disk.shrink.unavailable = "Die Verkleinerungsfunktion ist nicht verfügbar,\n\nweil Sie entweder eine alte Version eines VMware-Produkts ausführen oder weil zu viele Kommunikationskanäle offen sind.\n\nWenn Sie eine alte Version eines VMware-Produkts ausführen, sollten Sie ein Upgrade in Erwägung ziehen.\n\nWenn zu viele Kommunikationskanäle geöffnet sind, sollten Sie Ihre virtuelle Maschine aus- und anschließend wieder einschalten.\n"
disk.shrink.ignoreFreeSpaceWarnings = "Ignorieren Sie während des Verkleinerungsvorgangs etwaige Warnungen bezüglich des Speicherplatzes.\n"
@@ -62,33 +68,35 @@ disk.wiper.error = "Fehler: %1$s"
disk.wiper.file.error = "Fehler, Erstellen der Wiper-Datei nicht möglich.\n"
-disk.wiper.progress = "\rFortschritt: %1$d"
+disk.wiper.progress = "\rProgress: %1$d"
error.missing = "%1$s: %2$s fehlt\n"
error.noadmin.posix = "%1$s: Sie müssen root-Benutzer sein, um die %2$s-Vorgänge auszuführen.\n"
-error.noadmin.win = "%1$s: Zum Ausführen der %2$s-Vorgänge sind Administratorberechtigungen erforderlich.\nVerwenden Sie eine Administrator-Eingabeaufforderung, um diese Aufgaben fertig zu stellen.\n"
+error.noadmin.win = "%1$s: Zum Ausführen der %2$s-Vorgänge sind Administratorberechtigungen erforderlich.\nVerwenden Sie eine Administrator-Eingabeaufforderung, um diese Aufgaben abzuschließen.\n"
error.novirtual = "%1$s muss innerhalb einer virtuellen Maschine ausgeführt werden.\n"
error.unknown = "%1$s: %2$s '%3$s' unbekannt\n"
-help.device = "%1$s: Funktionen für die Hardwaregeräte der virtuellen Maschine\nNutzung: %2$s %3$s <Unterbefehl> [argumente]\n'dev' ist der Name des Geräts.\n\nUnterbefehle:\n enable <dev>: Aktivieren des Geräts 'dev' \n disable <dev>: Deaktivieren des Geräts 'dev'\n list: Liste aller verfügbaren Geräte\n status <dev>: Ausgabe des Status eines Geräts\n"
+help.device = "%1$s: Funktionen für die Hardwaregeräte der virtuellen Maschine\nNutzung: %2$s %3$s <Unterbefehl> [Argumente]\n'dev' ist der Name des Geräts.\n\nUnterbefehle:\n enable <dev>: Aktivieren des Geräts 'dev' \n disable <dev>: Deaktivieren des Geräts 'dev'\n list: Auflisten aller verfügbaren Geräte\n status <dev>: Ausgeben des Status eines Geräts\n"
-help.disk = "%1$s: Führt Verkleinerungen von Festplatten durch\nNutzung: %2$s %3$s <Unterbefehl> [argumente]\n\nUnterbefehle:\n list: Liste der verfügbaren Speicherorte\n shrink <Speicherort>: Löscht und verkleinert ein Dateisystem am angegebenen Speicherort\n shrinkonly: Verkleinert alle Festplatten\n wipe <Speicherort>: Löscht ein Dateisystem am angegebenen Speicherort\n"
+help.disk = "%1$s: Führt Verkleinerungen von Festplatten durch\nNutzung: %2$s %3$s <Unterbefehl> [Argumente]\n\nUnterbefehle:\n list: Auflisten der verfügbaren Speicherorte\n shrink <Speicherort>: Löschen und Verkleinern eines Dateisystems am angegebenen Speicherort\n shrinkonly: Verkleinern alle Festplatten\n wipe <Speicherort>: Löschen eines Dateisystems am angegebenen Speicherort\n"
help.hint = "Siehe '%1$s %2$s%3$s%4$s' für weitere Informationen.\n"
-help.main = "Nutzung: %1$s <Befehl> [Optionen] [Unterbefehl]\nWenn Sie Hilfe zu einem bestimmten Befehl benötigen, geben Sie '%2$s %3$s <Befehl>' ein.\nGeben Sie '%4$s -v' ein, um die VMware Tools-Version anzuzeigen.\nVerwenden Sie die Option '-q' zum Unterdrücken der stdout-Ausgabe.\nFür meisten Befehle gibt es Unterbefehle.\n\nVerfügbare Befehle:\n device\n disk\n script\n stat\n timesync\n upgrade (nicht auf allen Betriebssystemen verfügbar)\n"
+help.logging = "%1$s: Toolsprotokollierung verändern\nNutzung: %2$s %3$s level <Unterbefehl> <Dienstname> <Ebene>\n\nUnterbefehle:\n get <Dienstname>: Anzeige der aktuellen Ebene\n set <Dienstname> <Ebene>: Einrichten der aktuellen Ebene\n\n<Dienstname> kann jeder unterstützte Dienst sein wie vmsvc oder vmusr\n<Ebene> kann für einen Fehler, ein kritisches Ereignis, eine Warnung, Info, Meldung oder ein Debugging stehen \n Standard ist %4$s\n"
+
+help.main = "Nutzung: %1$s <Befehl> [Optionen] [Unterbefehl]<\nGeben> Sie '%2$s %3$s <Befehl>' für die Hilfe zu einem bestimmten Befehl ein.\Geben Sie '%4$s -v' für die Anzeige der Version von VMware Tools ein.\nVerwenden Sie den Parameter'-q' zur Ausblendung der stdout-Ausgabe.\nDie meisten Befehle verwenden einen Unterbefehl.\n\nVerfügbare Befehle:\n device\n disk\n logging\n script\n stat\n timesync\n upgrade (nicht für alle Betriebssysteme verfügbar)\n"
-help.script = "%1$s: Steuerung der Skripts, die als Reaktion auf Betriebsvorgänge ausgeführt werden\nNutzung: %2$s %3$s <power|resume|suspend|shutdown> <Unterbefehl> [argumente]\n\nUnterbefehle:\n enable: Aktivieren des angegebenen Skripts und Wiederherstellen dessen Pfads auf den Standardpfad\n disable: Deaktivieren des vorhandenen Skripts\n set <Vollständiger Pfad>: Festlegen des angegebenen Skripts auf den angegebenen Pfad\n default: Ausgabe des Standardpfads des angegebenen Skripts\n current: Ausgabe des aktuellen Pfads des angegebenen Skripts\n"
+help.script = "%1$s: Steuerung der Skripts, die als Reaktion auf Betriebsvorgänge ausgeführt werden\nNutzung: %2$s %3$s <power|resume|suspend|shutdown> <Unterbefehl> [Argumente]\n\nUnterbefehle:\n enable: Aktivieren des angegebenen Skripts und Wiederherstellen dessen Pfads auf den Standardpfad\n disable: Deaktivieren des vorhandenen Skripts\n set <Vollständiger Pfad>: Festlegen des angegebenen Skripts auf den angegebenen Pfad\n default: Ausgeben des Standardpfads des angegebenen Skripts\n current: Ausgeben des aktuellen Pfads des angegebenen Skripts\n"
-help.stat = "%1$s: Ausgabe nützlicher Gast- und Hostinformationen\nNutzung: %2$s %3$s <Unterbefehl>\n\nUnterbefehle:\n hosttime: Ausgabe der Hostuhrzeit\n speed: Ausgabe der CPU-Geschwindigkeit in MHz\nUnterbefehle nur für ESX-Gäste:\n sessionid: Ausgabe der aktuellen Sitzungs-ID\n balloon: Ausgabe von Informationen zum Arbeitsspeicher-Ballooning\n swap: Ausgabe von Informationen zur Arbeitsspeicherauslagerung\n memlimit: Ausgabe von Informationen zur Arbeitsspeicherlimitierungen\n memres: Ausgabe von Informationen zur Arbeitsspeicherreservierung\n cpures: Ausgabe von Informationen zur CPU-Reservierung\n cpulimit: Ausgabe von Informationen zu CPU-Limitierungen\n"
+help.stat = "%1$s: Drucken von hilfreichen Gast- und Hostinformationen\nNutzung: %2$s %3$s <Unterbefehl>\n\nUnterbefehle:\n hosttime: Ausgeben der Hostuhrzeit\n speed: Ausgeben der CPU-Geschwindigkeit in MHz\nUnterbefehle nur für ESX-Gäste:\n sessionid: Ausgeben der aktuellen Sitzungs-ID\n balloon: Ausgeben der Balloon-Arbeitsspeicher-Informationen\n swap: Ausgeben der Auslagerungsinformationen für den Arbeitsspeicher\n memlimit: Ausgeben des Arbeitsspeicher-Limits\n memres: Ausgeben der Arbeitsspeicherreservierung\n cpures: Ausgeben der CPU-Reservierung\n cpulimit: Ausgeben des CPU-Limits\n"
-help.timesync = "%1$s: Funktionen zum Steuern der Uhrzeitsynchronisierung auf dem Gastbetriebssystem\nNutzung: %2$s %3$s <Unterbefehl>\n\nUnterbefehle:\n enable: Aktivieren der Uhrzeitsynchronisierung\n disable: Deaktivieren der Uhrzeitsynchronisierung\n status: Ausgabe des Status der Uhrzeitsynchronisierung\n"
+help.timesync = "%1$s: Funktionen für die Steuerung der Zeitsynchronisierung auf dem Gastbetriebssystem\Nutzung: %2$s %3$s <Unterbefehl>\n\nUnterbefehle:\n enable: Aktivieren der Zeitsynchronisierung\n disable: Deaktivieren der Zeitsynchronisierung\n status: Ausgeben des Status der Zeitsynchronisierung\n"
-help.upgrade = "%1$s: Funktionen für das Upgrade von VMware Tools.\nNutzung: %2$s %3$s <Unterbefehl> [argumente]\nUnterbefehle:\n status: Überprüfen des Upgrade-Status für VMware Tools.\n start: Starten eines automatischen Upgrades von VMware Tools.\n\nDamit die Upgrades funktionieren, muss der VMware Tools-Dienst ausgeführt werden.\n"
+help.upgrade = "%1$s: Funktionen für das Upgrade von VMware Tools.\nNutzung: %2$s %3$s <Unterbefehl> [Argumente]\nUnterbefehle:\n status: Überprüfen des Upgrade-Status für VMware Tools.\n start: Starten eines automatischen Upgrade von VMware Tools.\n\nDamit die Upgrades funktionieren, muss der VMware Tools-Dienst ausgeführt werden.\n"
option.disabled = "Deaktiviert"
diff --git a/open-vm-tools/toolbox/l10n/ja.vmsg b/open-vm-tools/toolbox/l10n/ja.vmsg
index c6fdd565..f2bfd5f6 100644
--- a/open-vm-tools/toolbox/l10n/ja.vmsg
+++ b/open-vm-tools/toolbox/l10n/ja.vmsg
@@ -1,5 +1,5 @@
##########################################################
-# Copyright (C) 2010-2015 VMware, Inc. All rights reserved.
+# Copyright (C) 2010 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
@@ -20,6 +20,12 @@ arg.command = "コマンド"
arg.devicename = "デãƒã‚¤ã‚¹å"
+arg.logging.level = "ログ レベル"
+
+arg.logging.service = "サービスåã®ãƒ­ã‚°"
+
+arg.logging.subcommand = "æ“作ã®ãƒ­ã‚°"
+
arg.mountpoint = "マウント ãƒã‚¤ãƒ³ãƒˆ"
arg.scriptpath = "スクリプト パス"
@@ -38,9 +44,9 @@ disk.shrink.canceled = "ディスク圧縮ãŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œã¾ã—ãŸã€‚\n
disk.shrink.complete = "ディスクã®åœ§ç¸®ãŒå®Œäº†ã—ã¾ã—ãŸã€‚\n"
-disk.shrink.conflict = "エラー。ツールボックスã§ãƒ‡ã‚£ã‚¹ã‚¯ã®åœ§ç¸®ãŒæœ‰åŠ¹ã§ã‚ã‚‹ã¨åˆ¤æ–­ã•ã‚Œã¾ã—ãŸãŒã€ãƒ›ã‚¹ãƒˆã§ã¯ç„¡åŠ¹ã¨åˆ¤æ–­ã•ã‚Œã¦ã„ã¾ã™ã€‚\n\nツールボックスをã„ã£ãŸã‚“é–‰ã˜ã¦ã‹ã‚‰é–‹ã„ã¦ã€ãƒ›ã‚¹ãƒˆã¨åŒæœŸã—ã¦ãã ã•ã„。\n"
+disk.shrink.conflict = "エラー。ツールボックスã§ãƒ‡ã‚£ã‚¹ã‚¯ã®åœ§ç¸®ãŒæœ‰åŠ¹ã§ã‚ã‚‹ã¨åˆ¤æ–­ã•ã‚Œã¾ã—ãŸãŒã€ãƒ›ã‚¹ãƒˆã§ã¯ç„¡åŠ¹ã§ã‚ã‚‹ã¨åˆ¤æ–­ã•ã‚Œã¦ã„ã¾ã™ã€‚\n\n ツールボックスをã„ã£ãŸã‚“é–‰ã˜ã¦ã‹ã‚‰é–‹ã„ã¦ã€ãƒ›ã‚¹ãƒˆã¨åŒæœŸã—ã¦ãã ã•ã„。\n"
-disk.shrink.disabled = "ディスクã®åœ§ç¸®ã¯ã“ã®ä»®æƒ³ãƒžã‚·ãƒ³ã§ã¯ç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚\n\nリンク クローンã€ãƒªãƒ³ã‚¯ クローンã®è¦ªã€\n事å‰å‰²ã‚Šå½“ã¦æ¸ˆã¿ã®ãƒ‡ã‚£ã‚¹ã‚¯ã€ã‚¹ãƒŠãƒƒãƒ—ショットã€ã¾ãŸã¯ãã®ä»–ã®è¦å› ã«ã‚ˆã‚Šã€åœ§ç¸®ã¯ç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚\n詳細ã«ã¤ã„ã¦ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ マニュアルをå‚ç…§ã—ã¦ãã ã•ã„。\n"
+disk.shrink.disabled = "ディスクã®åœ§ç¸®ã¯ã“ã®ä»®æƒ³ãƒžã‚·ãƒ³ã§ã¯ç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚\n\nリンクã•ã‚ŒãŸã‚¯ãƒ­ãƒ¼ãƒ³ã€ãƒªãƒ³ã‚¯ã•ã‚ŒãŸã‚¯ãƒ­ãƒ¼ãƒ³ã®è¦ªã€\n事å‰å‰²ã‚Šå½“ã¦æ¸ˆã¿ã®ãƒ‡ã‚£ã‚¹ã‚¯ã€ã‚¹ãƒŠãƒƒãƒ—ショットã€ã¾ãŸã¯ãã®ä»–ã®è¦å› ã«ã‚ˆã‚Šã€åœ§ç¸®ã¯ç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚\n詳細ã«ã¤ã„ã¦ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ マニュアルをå‚ç…§ã—ã¦ãã ã•ã„。\n"
disk.shrink.error = "圧縮中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %1$s\n"
@@ -52,7 +58,7 @@ disk.shrink.partition.notfound = "パーティション %1$s ãŒè¦‹ã¤ã‹ã‚Šã¾ã
disk.shrink.partition.unsupported = "パーティション %1$s ã¯åœ§ç¸®ã§ãã¾ã›ã‚“\n"
-disk.shrink.unavailable = "実行ã—ã¦ã„ã‚‹ VMware 製å“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒå¤ã„ã‹ã€\n\né–‹ã„ã¦ã„る通信ãƒãƒ£ãƒãƒ«ã®æ•°ãŒå¤šã™ãŽã‚‹ãŸã‚ã€åœ§ç¸®æ©Ÿèƒ½ã‚’使用ã§ãã¾ã›ã‚“。\n\nVMware 製å“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒå¤ã„å ´åˆã¯ã€ã‚¢ãƒƒãƒ—グレードを検討ã—ã¦ãã ã•ã„。\n\né–‹ã„ã¦ã„る通信ãƒãƒ£ãƒãƒ«ã®æ•°ãŒå¤šã™ãŽã‚‹å ´åˆã¯ã€ä»®æƒ³ãƒžã‚·ãƒ³ã‚’パワー オフã—ã¦ã‹ã‚‰å†åº¦ãƒ‘ワー オンã—ã¦ãã ã•ã„。\n"
+disk.shrink.unavailable = "圧縮機能ãŒä½¿ç”¨ã§ãã¾ã›ã‚“。\n\n実行ã—ã¦ã„ã‚‹ VMware 製å“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒå¤ã„ã‹ã€é–‹ã„ã¦ã„る通信ãƒãƒ£ãƒãƒ«ãŒå¤šã™ãŽã‚‹ã“ã¨ãŒåŽŸå› ã¨ã—ã¦è€ƒãˆã‚‰ã‚Œã¾ã™ã€‚\n\nVMware 製å“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒå¤ã„å ´åˆã¯ã€ã‚¢ãƒƒãƒ—グレードを検討ã—ã¦ãã ã•ã„。\n\n多数ã®é€šä¿¡ãƒãƒ£ãƒãƒ«ã‚’é–‹ã„ã¦ã„ã‚‹å ´åˆã¯ã€ä»®æƒ³ãƒžã‚·ãƒ³ã‚’パワーオフã—ã¦ã‹ã‚‰å†é–‹ã—ã¦ãã ã•ã„。\n"
disk.shrink.ignoreFreeSpaceWarnings = "圧縮プロセス中ã«è¡¨ç¤ºã•ã‚Œã‚‹ãƒ‡ã‚£ã‚¹ã‚¯é ˜åŸŸã«é–¢ã™ã‚‹è­¦å‘Šã¯ã™ã¹ã¦ç„¡è¦–ã—ã¦ãã ã•ã„。\n"
@@ -68,27 +74,29 @@ error.missing = "%1$s: %2$s ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“\n"
error.noadmin.posix = "%1$s: %2$s æ“作を実行ã™ã‚‹ã«ã¯ã€root ユーザーã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\n"
-error.noadmin.win = "%1$s: %2$s æ“作を実行ã™ã‚‹ã«ã¯ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“れらã®ã‚¿ã‚¹ã‚¯ã‚’実行ã™ã‚‹ã«ã¯ã€ç®¡ç†è€…コマンド プロンプトを使用ã—ã¦ãã ã•ã„。\n"
+error.noadmin.win = "%1$s: %2$s æ“作を実行ã™ã‚‹ã«ã¯ã€ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚\nã“れらã®ã‚¿ã‚¹ã‚¯ã‚’実行ã™ã‚‹ã«ã¯ã€ç®¡ç†è€…コマンド プロンプトを使用ã—ã¦ãã ã•ã„。\n"
error.novirtual = "%1$s ã¯ä»®æƒ³ãƒžã‚·ãƒ³å†…ã§å®Ÿè¡Œã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\n"
-error.unknown = "%1$s: ä¸æ˜Žãª %2$s「%3$sã€\n"
+error.unknown = "%1$s: ä¸æ˜Žãª %2$s '%3$s'\n"
-help.device = "%1$s: 仮想マシンã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ デãƒã‚¤ã‚¹ã«é–¢é€£ã™ã‚‹æ©Ÿèƒ½\n使用方法: %2$s %3$s <サブコマンド> [引数]\ndev ã«ã¯ãƒ‡ãƒã‚¤ã‚¹ã®åå‰ã‚’指定ã—ã¾ã™ã€‚\n\nサブコマンド: \n enable <dev>: デãƒã‚¤ã‚¹ dev を有効ã«ã™ã‚‹\n disable <dev>: デãƒã‚¤ã‚¹ dev を無効ã«ã™ã‚‹\n list: 有効ãªãƒ‡ãƒã‚¤ã‚¹ã‚’一覧表示\n status <dev>: デãƒã‚¤ã‚¹ã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’出力\n"
+help.device = "%1$s: 仮想マシンã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ デãƒã‚¤ã‚¹ã«é–¢é€£ã™ã‚‹æ©Ÿèƒ½\n使用方法: %2$s %3$s <サブコマンド> [引数]\ndev ã«ã¯ãƒ‡ãƒã‚¤ã‚¹åを指定ã—ã¾ã™ã€‚\n\nサブコマンド:\n enable <デãƒã‚¤ã‚¹>: デãƒã‚¤ã‚¹ dev を有効ã«ã™ã‚‹\n disable <デãƒã‚¤ã‚¹>: デãƒã‚¤ã‚¹ dev を無効ã«ã™ã‚‹\n list: 有効ãªãƒ‡ãƒã‚¤ã‚¹ã‚’一覧表示\n status <デãƒã‚¤ã‚¹>: デãƒã‚¤ã‚¹ã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’出力\n"
help.disk = "%1$s: ディスク圧縮æ“作を実行\n使用方法: %2$s %3$s <サブコマンド> [引数]\n\nサブコマンド:\n list: 使用å¯èƒ½ãªå ´æ‰€ã‚’一覧表示\n shrink <場所>: 指定ã•ã‚ŒãŸå ´æ‰€ã®ãƒ•ã‚¡ã‚¤ãƒ« システムをワイプãŠã‚ˆã³åœ§ç¸®\n shrinkonly: ã™ã¹ã¦ã®ãƒ‡ã‚£ã‚¹ã‚¯ã‚’圧縮\n wipe <場所>: 指定ã•ã‚ŒãŸå ´æ‰€ã®ãƒ•ã‚¡ã‚¤ãƒ« システムをワイプ\n"
help.hint = "詳細ã«ã¤ã„ã¦ã¯ã€ã€Œ%1$s %2$s%3$s%4$sã€ã‚’å‚ç…§ã—ã¦ãã ã•ã„。\n"
-help.main = "使用方法: %1$s <コマンド> [オプション] [サブコマンド]\n「%2$s %3$s <コマンド>ã€ã¨å…¥åŠ›ã™ã‚‹ã¨ã€ãã®ã‚³ãƒžãƒ³ãƒ‰ã®ãƒ˜ãƒ«ãƒ—を表示ã§ãã¾ã™ã€‚\nVMware Tools ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’確èªã™ã‚‹ã«ã¯ã€Œ%4$s -vã€ã¨å…¥åŠ›ã—ã¾ã™ã€‚\nstdout 出力を抑止ã™ã‚‹ã«ã¯ã€Œ-qã€ã‚ªãƒ—ションを使用ã—ã¾ã™ã€‚\nã»ã¨ã‚“ã©ã®ã‚³ãƒžãƒ³ãƒ‰ã§ã¯ã‚µãƒ–コマンドも使用ã•ã‚Œã¾ã™ã€‚\n\n使用å¯èƒ½ãªã‚³ãƒžãƒ³ãƒ‰: \n device\n disk\n script\n stat\n timesync\n upgrade(オペレーティング システム ã«ã‚ˆã£ã¦ã¯ä½¿ç”¨ã§ããªã„å ´åˆã‚‚ã‚ã‚Šã¾ã™ï¼‰\n"
+help.logging = "%1$s: Tools ログを変更ã—ã¾ã™\n使用法: %2$s %3$s level <subcommand> <servicename> <level>\n\nサブコマンド:\n <servicename> ã®å–å¾—: ç¾åœ¨ã®ãƒ¬ãƒ™ãƒ«ã‚’表示ã—ã¾ã™\n <servicename> <level> ã®è¨­å®š: ç¾åœ¨ã®ãƒ¬ãƒ™ãƒ«ã‚’設定ã—ã¾ã™\n\n<servicename> ã¯ã€vmsvc ã‚„ vmusr ãªã©ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„るサービスを指定ã§ãã¾ã™\n<level> ã¯ã€ã‚¨ãƒ©ãƒ¼ã€ã‚¯ãƒªãƒ†ã‚£ã‚«ãƒ«ã€è­¦å‘Šã€æƒ…å ±ã€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã€ãƒ‡ãƒãƒƒã‚°ã®ã„ãšã‚Œã‹ã‚’指定ã§ãã¾ã™\n デフォルト㯠%4$s ã§ã™\n"
+
+help.main = "使用方法: %1$s <コマンド> [オプション] [サブコマンド]\n特定ã®ã‚³ãƒžãƒ³ãƒ‰ã®ãƒ˜ãƒ«ãƒ—ã«ã¤ã„ã¦ã¯ã€'%2$s %3$s <コマンド>' を入力ã—ã¾ã™ã€‚\nVMware Tools ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’確èªã™ã‚‹ã«ã¯ã€'%4$s -v' を入力ã—ã¾ã™ã€‚\nstdout 出力を行ã‚ãªã„å ´åˆã¯ '-q' オプションを使用ã—ã¾ã™ã€‚\nã»ã¨ã‚“ã©ã®ã‚³ãƒžãƒ³ãƒ‰ã§ã¯ã€ã‚µãƒ–コマンドを使用ã—ã¾ã™ã€‚\n\n使用å¯èƒ½ãªã‚³ãƒžãƒ³ãƒ‰:\n device\n disk\n logging\n script\n stat\n timesync\n upgrade (ã™ã¹ã¦ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚° システムã§ä½¿ç”¨ã§ãã‚‹ã‚ã‘ã§ã¯ã‚ã‚Šã¾ã›ã‚“)\n"
-help.script = "%1$s: é›»æºæ“作ã«å¯¾å¿œã—ã¦å®Ÿè¡Œã•ã‚Œã‚‹ã‚¹ã‚¯ãƒªãƒ—トを制御\n使用方法: %2$s %3$s <power|resume|suspend|shutdown> <サブコマンド> [引数]\n\nサブコマンド: \n enable: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トを有効ã«ã—ã¦ã€ãã®ãƒ‘スをデフォルトã«å¾©å…ƒ\n disable: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トを無効ã«ã™ã‚‹\n set <完全パス>: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トを指定ã•ã‚ŒãŸãƒ‘スã«è¨­å®š\n default: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ‘スを出力\n current: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トã®ç¾åœ¨ã®ãƒ‘スを出力\n"
+help.script = "%1$s: é›»æºæ“作ã«å¯¾å¿œã—ã¦å®Ÿè¡Œã•ã‚Œã‚‹ã‚¹ã‚¯ãƒªãƒ—トを制御\n使用方法: %2$s %3$s <power|resume|suspend|shutdown> <サブコマンド> [引数]\n\nサブコマンド:\n enable: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トを有効ã«ã—ã¦ã€ãã®ãƒ‘スをデフォルトã«å¾©å…ƒ\n disable: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トを無効ã«ã™ã‚‹\n set <フル パス>: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トを指定ã•ã‚ŒãŸãƒ‘スã«è¨­å®š\n default: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ‘スを出力\n current: 指定ã•ã‚ŒãŸã‚¹ã‚¯ãƒªãƒ—トã®ç¾åœ¨ã®ãƒ‘スを出力\n"
-help.stat = "%1$s: å½¹ã«ç«‹ã¤ã‚²ã‚¹ãƒˆãŠã‚ˆã³ãƒ›ã‚¹ãƒˆæƒ…報をå°åˆ·\n使用方法: %2$s %3$s <サブコマンド>\n\nサブコマンド: \n hosttime: ホスト時間を出力\n speed: CPU 速度を MHz å˜ä½ã§å‡ºåŠ›\nESX ゲスト専用サブコマンド: \n sessionid: ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ ID を出力\n balloon: メモリ ãƒãƒ«ãƒ¼ãƒ‹ãƒ³ã‚°æƒ…報を出力\n swap: メモリ スワップ情報を出力\n memlimit: メモリ制é™æƒ…報を出力\n memres: メモリ予約情報を出力\n cpures: CPU 予約情報を出力\n cpulimit: CPU 制é™æƒ…報を出力\n"
+help.stat = "%1$s: å½¹ã«ç«‹ã¤ã‚²ã‚¹ãƒˆãŠã‚ˆã³ãƒ›ã‚¹ãƒˆæƒ…報を出力\n使用方法: %2$s %3$s <サブコマンド>\n\nサブコマンド:\n hosttime: ホスト時刻を出力\n speed: CPU 速度 (MHz) を出力\nESX ゲストã®ã¿ã®ã‚µãƒ–コマンド:\n sessionid: ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ ID を出力\n balloon: メモリã®ãƒãƒ«ãƒ¼ãƒ‹ãƒ³ã‚°æƒ…報を出力\n swap: メモリã®ã‚¹ãƒ¯ãƒƒãƒ—情報を出力\n memlimit: メモリã®åˆ¶é™æƒ…報を出力\n memres: メモリã®äºˆç´„情報を出力\n cpures: CPU ã®äºˆç´„情報を出力\n cpulimit: CPU ã®åˆ¶é™æƒ…報を出力\n"
-help.timesync = "%1$s: ゲスト OS ã®æ™‚刻åŒæœŸã‚’制御ã™ã‚‹æ©Ÿèƒ½\n使用方法: %2$s %3$s <サブコマンド>\n\nサブコマンド: \n enable: 時間åŒæœŸã‚’有効ã«ã™ã‚‹\n disable: 時間åŒæœŸã‚’無効ã«ã™ã‚‹\n status: 時間åŒæœŸã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’出力\n"
+help.timesync = "%1$s: ゲスト OS ã®æ™‚刻ã®åŒæœŸã‚’制御ã™ã‚‹ãŸã‚ã®æ©Ÿèƒ½\n使用方法: %2$s %3$s <サブコマンド>\n\nサブコマンド:\n enable: 時刻ã®åŒæœŸã‚’有効ã«ã™ã‚‹\n disable: 時刻ã®åŒæœŸã‚’無効ã«ã™ã‚‹\n status: 時刻ã®åŒæœŸã®çŠ¶æ…‹ã‚’出力\n"
-help.upgrade = "%1$s: VMware Tools ã®ã‚¢ãƒƒãƒ—グレードã«é–¢é€£ã™ã‚‹æ©Ÿèƒ½ã€‚\n使用方法: %2$s %3$s <サブコマンド> [引数]\nサブコマンド: \n status: VMware Tools ã®ã‚¢ãƒƒãƒ—グレード ステータスを確èª\n start: VMware Tools ã®è‡ªå‹•ã‚¢ãƒƒãƒ—グレードを開始\n\nアップグレードãŒæ©Ÿèƒ½ã™ã‚‹ã«ã¯ã€VMware Tools サービスを実行ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\n"
+help.upgrade = "%1$s: VMware Tools ã®ã‚¢ãƒƒãƒ—グレードã«é–¢é€£ã™ã‚‹æ©Ÿèƒ½ã€‚\n使用方法: %2$s %3$s <サブコマンド> [引数]\nサブコマンド:\n status: VMware Tools ã®ã‚¢ãƒƒãƒ—グレード ステータスを確èª\n start: VMware Tools ã®è‡ªå‹•ã‚¢ãƒƒãƒ—グレードを開始\n\nアップグレードãŒæ©Ÿèƒ½ã™ã‚‹ã«ã¯ã€VMware Tools サービスを実行ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚\n"
option.disabled = "無効"
diff --git a/open-vm-tools/toolbox/l10n/ko.vmsg b/open-vm-tools/toolbox/l10n/ko.vmsg
index 4bed8322..1e8e1b65 100644
--- a/open-vm-tools/toolbox/l10n/ko.vmsg
+++ b/open-vm-tools/toolbox/l10n/ko.vmsg
@@ -1,5 +1,5 @@
##########################################################
-# Copyright (C) 2010-2015 VMware, Inc. All rights reserved.
+# Copyright (C) 2010 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
@@ -20,6 +20,12 @@ arg.command = "명령"
arg.devicename = "디바ì´ìŠ¤ ì´ë¦„"
+arg.logging.level = "로깅 수준"
+
+arg.logging.service = "로깅 서비스 ì´ë¦„"
+
+arg.logging.subcommand = "로깅 작업"
+
arg.mountpoint = "마운트 지ì "
arg.scriptpath = "스í¬ë¦½íŠ¸ 경로"
@@ -38,9 +44,9 @@ disk.shrink.canceled = "ë””ìŠ¤í¬ ì¶•ì†Œê°€ 취소ë˜ì—ˆìŠµë‹ˆë‹¤.\n"
disk.shrink.complete = "ë””ìŠ¤í¬ ì¶•ì†Œê°€ 완료ë˜ì—ˆìŠµë‹ˆë‹¤.\n"
-disk.shrink.conflict = "오류. ë„구 ìƒìžì—ì„œ ë””ìŠ¤í¬ ì¶•ì†ŒëŠ” 호스트ì—ì„œ ì´ë¥¼ 사용하지 않는 ìƒíƒœì¼ ë•Œ 사용ë©ë‹ˆë‹¤.\n\n 호스트와 ë™ê¸°í™”하려면 ë„구 ìƒìžë¥¼ ë‹«ì€ í›„ 다시 여십시오.\n"
+disk.shrink.conflict = "오류. ë„구 ìƒìžì—서는 ë””ìŠ¤í¬ ì¶•ì†Œë¥¼ 사용한다고 간주하는 반면 호스트ì—서는 ë””ìŠ¤í¬ ì¶•ì†Œë¥¼ 사용하지 않는다고 간주합니다.\n\në„구 ìƒìžë¥¼ 닫았다가 다시 ì—´ì–´ ì´ ì„¤ì •ì„ í˜¸ìŠ¤íŠ¸ì™€ ë™ê¸°í™”하십시오.\n"
-disk.shrink.disabled = "ì´ ê°€ìƒ ì‹œìŠ¤í…œì— ëŒ€í•´ ë””ìŠ¤í¬ ì¶•ì†Œê°€ 사용ë˜ì§€ 않습니다.\n\nì—°ê²°ëœ ë³µì œ, ì—°ê²°ëœ ë³µì œì˜ ìƒìœ„, 미리 í• ë‹¹ëœ ë””ìŠ¤í¬, ìŠ¤ëƒ…ìƒ·ì— ëŒ€í•´ \n축소가 사용ë˜ì§€ 않거나 다른 ì›ì¸ ë•Œë¬¸ì¼ ìˆ˜ 있습니다. \nìžì„¸í•œ ë‚´ìš©ì€ ì‚¬ìš© 설명서를 참조하십시오.\n"
+disk.shrink.disabled = "ì´ ê°€ìƒ ì‹œìŠ¤í…œì— ëŒ€í•´ ë””ìŠ¤í¬ ì¶•ì†Œê°€ 사용ë˜ì§€ 않습니다.\n\në§í¬ë“œ í´ë¡ , ë§í¬ë“œ í´ë¡ ì˜ ìƒìœ„, 미리 í• ë‹¹ëœ ë””ìŠ¤í¬, ìŠ¤ëƒ…ìƒ·ì— ëŒ€í•´ \n축소가 사용ë˜ì§€ 않거나 다른 ì›ì¸ ë•Œë¬¸ì¼ ìˆ˜ 있습니다. \nìžì„¸í•œ ë‚´ìš©ì€ ì‚¬ìš© 설명서를 참조하십시오.\n"
disk.shrink.error = "축소하는 ë™ì•ˆ 오류 ë°œìƒ: %1$s\n"
@@ -52,7 +58,7 @@ disk.shrink.partition.notfound = "파티션 %1$sì„(를) ì°¾ì„ ìˆ˜ ì—†ìŒ\n"
disk.shrink.partition.unsupported = "파티션 %1$s 축소 불가능\n"
-disk.shrink.unavailable = "축소 ê¸°ëŠ¥ì„ ì‚¬ìš©í•  수 없습니다. \n\n실행 ì¤‘ì¸ VMware ì œí’ˆì´ ì˜¤ëž˜ëœ ë²„ì „ì´ê±°ë‚˜ 너무 ë§Žì€ í†µì‹  채ë„ì´ ì—´ë ¤ 있기 때문입니다.\n\n ì˜¤ëž˜ëœ ë²„ì „ì˜ VMware ì œí’ˆì´ ì‹¤í–‰ë˜ê³  있다면 업그레ì´ë“œë¥¼ 고려해야 합니다. \n\n통신 채ë„ì´ ë„ˆë¬´ ë§Žì´ ì—´ë ¤ 있는 경우ì—는 ê°€ìƒ ì‹œìŠ¤í…œì˜ ì „ì›ì„ ëˆ í›„ 다시 켜야 합니다.\n"
+disk.shrink.unavailable = "축소 ê¸°ëŠ¥ì„ ì‚¬ìš©í•  수 없습니다.\n\nì´ì „ ë²„ì „ì˜ VMware ì œí’ˆì„ ì‹¤í–‰í•˜ê³  있거나 통신 채ë„ì´ ë„ˆë¬´ ë§Žì´ ì—´ë ¤ 있기 때문입니다.\n\nì´ì „ ë²„ì „ì˜ VMware ì œí’ˆì„ ì‹¤í–‰í•˜ê³  있는 경우ì—는 업그레ì´ë“œë¥¼ 고려해 보십시오.\n너무 ë§Žì€ í†µì‹  채ë„ì´ ì—´ë ¤ 있는 경우ì—는 ê°€ìƒ ì‹œìŠ¤í…œì˜ ì „ì›ì„ ê»ë‹¤ê°€ 다시 켜야 합니다.\n"
disk.shrink.ignoreFreeSpaceWarnings = "축소 프로세스가 실행ë˜ëŠ” ë™ì•ˆì—는 ë””ìŠ¤í¬ ê³µê°„ì— ëŒ€í•œ 주ì˜ë¥¼ 무시하십시오.\n"
@@ -68,25 +74,27 @@ error.missing = "%1$s: %2$sì´(ê°€) ì—†ìŒ\n"
error.noadmin.posix = "%1$s: %2$s ìž‘ì—…ì€ ë£¨íŠ¸ 사용ìžë§Œ 수행할 수 있습니다.\n"
-error.noadmin.win = "%1$s: %2$s ìž‘ì—…ì„ ìˆ˜í–‰í•˜ë ¤ë©´ ê´€ë¦¬ìž ê¶Œí•œì´ í•„ìš”í•©ë‹ˆë‹¤.\nì´ëŸ¬í•œ 태스í¬ë¥¼ 완료하려면 ê´€ë¦¬ìž ëª…ë ¹ 프롬프트를 사용하십시오.\n"
+error.noadmin.win = "%1$s: %2$s ìž‘ì—…ì„ ìˆ˜í–‰í•˜ë ¤ë©´ ê´€ë¦¬ìž ê¶Œí•œì´ í•„ìš”í•©ë‹ˆë‹¤.\nì´ëŸ¬í•œ ìž‘ì—…ì„ ì™„ë£Œí•˜ë ¤ë©´ ê´€ë¦¬ìž ëª…ë ¹ 프롬프트를 사용하십시오.\n"
error.novirtual = "%1$sì€(는) ê°€ìƒ ì‹œìŠ¤í…œ 내부ì—ì„œ 실행해야 합니다.\n"
error.unknown = "%1$s: 알 수 없는 %2$s '%3$s'\n"
-help.device = "%1$s: ê°€ìƒ ì‹œìŠ¤í…œì˜ í•˜ë“œì›¨ì–´ 디바ì´ìŠ¤ì™€ ê´€ë ¨ëœ ê¸°ëŠ¥\n사용법: %2$s %3$s <하위 명령> [ì¸ìˆ˜]\ndev는 디바ì´ìŠ¤ ì´ë¦„입니다.\n\n하위 명령:\n enable <dev>: 디바ì´ìŠ¤ devê°€ 사용ë˜ë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤.\n disable <dev>: 디바ì´ìŠ¤ devê°€ 사용ë˜ì§€ ì•Šë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤.\n list: 사용 가능한 모든 디바ì´ìŠ¤ë¥¼ 나열합니다.\n status <dev>: 디바ì´ìŠ¤ì˜ ìƒíƒœë¥¼ 출력합니다.\n"
+help.device = "%1$s: ê°€ìƒ ì‹œìŠ¤í…œì˜ í•˜ë“œì›¨ì–´ 디바ì´ìŠ¤ì™€ ê´€ë ¨ëœ ê¸°ëŠ¥\n사용법: %2$s %3$s <하위 명령> [ì¸ìˆ˜]\ndev는 디바ì´ìŠ¤ ì´ë¦„입니다.\n\n하위 명령:\n enable <dev>: 디바ì´ìŠ¤ devê°€ 사용ë˜ë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤.\n disable <dev>: 디바ì´ìŠ¤ devê°€ 사용ë˜ì§€ ì•Šë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤.\n list: 사용 가능한 모든 디바ì´ìŠ¤ë¥¼ 나열합니다.\n status <dev>: 디바ì´ìŠ¤ì˜ ìƒíƒœë¥¼ 출력합니다.\n"
-help.disk = "%1$s: ë””ìŠ¤í¬ ì¶•ì†Œ ìž‘ì—…ì„ ìˆ˜í–‰í•©ë‹ˆë‹¤.\n사용법: %2$s %3$s <하위 명령> [ì¸ìˆ˜]\n\n하위 명령:\n list: 사용 가능한 위치를 나열합니다.\n shrink <위치>: ì§€ì •ëœ ìœ„ì¹˜ì—ì„œ íŒŒì¼ ì‹œìŠ¤í…œì„ ì§€ìš°ê³  축소합니다.\n shrinkonly: 모든 디스í¬ë¥¼ 축소합니다.\n wipe <위치>: ì§€ì •ëœ ìœ„ì¹˜ì—ì„œ íŒŒì¼ ì‹œìŠ¤í…œì„ ì§€ì›ë‹ˆë‹¤.\n"
+help.disk = "%1$s: ë””ìŠ¤í¬ ì¶•ì†Œ ìž‘ì—…ì„ ìˆ˜í–‰í•©ë‹ˆë‹¤.\n사용법: %2$s %3$s <하위명령> [ì¸ìˆ˜]\n\n하위 명령:\n list: 사용 가능한 위치를 나열합니다.\n shrink <위치>: ì§€ì •ëœ ìœ„ì¹˜ì—ì„œ íŒŒì¼ ì‹œìŠ¤í…œì„ ì§€ìš°ê³  축소합니다.\n shrinkonly: 모든 디스í¬ë¥¼ 축소합니다.\n wipe <위치>: ì§€ì •ëœ ìœ„ì¹˜ì—ì„œ íŒŒì¼ ì‹œìŠ¤í…œì„ ì§€ì›ë‹ˆë‹¤.\n"
help.hint = "ìžì„¸í•œ ë‚´ìš©ì„ ë³´ë ¤ë©´ '%1$s %2$s%3$s%4$s'ì„(를) ì‹œë„í•´ 보십시오.\n"
-help.main = "사용법: %1$s <명령> [옵션] [하위 명령]\n특정 ëª…ë ¹ì— ëŒ€í•œ ë„움ë§ì„ 보려면 '%2$s %3$s <명령>'ì„(를) 입력하십시오.\nVMware Tools ë²„ì „ì„ í™•ì¸í•˜ë ¤ë©´ '%4$s -v'를 입력하십시오.\nstdout ì¶œë ¥ì„ í‘œì‹œí•˜ì§€ 않으려면 '-q' ì˜µì…˜ì„ ì‚¬ìš©í•˜ì‹­ì‹œì˜¤.\nëŒ€ë¶€ë¶„ì˜ ëª…ë ¹ì— í•˜ìœ„ ëª…ë ¹ì´ ì‚¬ìš©ë©ë‹ˆë‹¤.\n\n사용 가능한 명령:\n device\n disk\n script\n stat\n timesync\n upgrade(ì¼ë¶€ ìš´ì˜ ì²´ì œì—서만 사용할 수 있ìŒ)\n"
+help.logging = "%1$s: ë„구 로깅 수정\n사용: %2$s %3$s 수준 <subcommand> <servicename> <level>\n\n하위 명령:\n <servicename> 가져오기: 현재 수준 표시\n <servicename> <level> 설정: 현재 수준 설정\n\n<servicename>ì€ vmsvc ë˜ëŠ” vmusrê³¼ ê°™ì€ ì§€ì› ì„œë¹„ìŠ¤ì¼ ìˆ˜ 있습니다.\n<level>ì€ ì˜¤ë¥˜, 중요, 경고, ì •ë³´, 메시지, 디버그 중 í•˜ë‚˜ì¼ ìˆ˜ 있습니다.\n ê¸°ë³¸ê°’ì€ %4$s입니다.\n"
+
+help.main = "사용법: %1$s <명령> [옵션] [하위 명령]\n특정 ëª…ë ¹ì— ëŒ€í•œ ë„움ë§ì„ 보려면 '%2$s %3$s <명령>'ì„(를) 입력합니다.\nVMware Tools ë²„ì „ì„ í™•ì¸í•˜ë ¤ë©´ '%4$s -v'를 입력합니다.\nstdout ì¶œë ¥ì„ í‘œì‹œí•˜ì§€ 않으려면 '-q' ì˜µì…˜ì„ ì‚¬ìš©í•©ë‹ˆë‹¤.\nëŒ€ë¶€ë¶„ì˜ ëª…ë ¹ì—는 하위 ëª…ë ¹ì´ ìžˆìŠµë‹ˆë‹¤.\n\n사용 가능한 명령:\n device\n disk\n logging\n script\n stat\n timesync\n upgrade(모든 ìš´ì˜ ì²´ì œì—ì„œ 사용할 수 있는 ê²ƒì€ ì•„ë‹˜)\n"
-help.script = "%1$s: ì „ì› ìž‘ì—…ì— ëŒ€í•œ ì‘답으로 실행ë˜ëŠ” 스í¬ë¦½íŠ¸ë¥¼ 제어합니다.\n사용법: %2$s %3$s <power|resume|suspend|shutdown> <하위 명령> [ì¸ìˆ˜]\n\n하위 명령:\n enable: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ê°€ 사용ë˜ë„ë¡ ì„¤ì •í•˜ê³  해당 경로를 기본값으로 ë³µì›í•©ë‹ˆë‹¤.\n disable: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ê°€ 사용ë˜ì§€ ì•Šë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤.\n set <ì „ì²´ 경로>: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ë¥¼ ì§€ì •ëœ ê²½ë¡œë¡œ 설정합니다.\n default: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ì˜ 기본 경로를 출력합니다.\n current: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ì˜ 현재 경로를 출력합니다.\n"
+help.script = "%1$s: ì „ì› ìž‘ì—…ì— ëŒ€í•œ ì‘답으로 실행ë˜ëŠ” 스í¬ë¦½íŠ¸ë¥¼ 제어합니다.\n사용법: %2$s %3$s <ì „ì›|재개|ì¼ì‹œ 중단|종료> <하위 명령> [ì¸ìˆ˜]\n\n하위 명령:\n enable: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ê°€ 사용ë˜ë„ë¡ ì„¤ì •í•˜ê³  해당 경로를 기본값으로 ë³µì›í•©ë‹ˆë‹¤.\n disable: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ê°€ 사용ë˜ì§€ ì•Šë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤.\n set <ì „ì²´ 경로>: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ë¥¼ ì§€ì •ëœ ê²½ë¡œë¡œ 설정합니다.\n default: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ì˜ 기본 경로를 출력합니다.\n current: ì§€ì •ëœ ìŠ¤í¬ë¦½íŠ¸ì˜ 현재 경로를 출력합니다.\n"
-help.stat = "%1$s: 유용한 게스트 ë° í˜¸ìŠ¤íŠ¸ 정보를 출력합니다.\n사용법: %2$s %3$s <하위 명령>\n\n하위 명령:\n hosttime: 호스트 ì‹œê°„ì„ ì¶œë ¥í•©ë‹ˆë‹¤.\n speed: CPU ì†ë„를 MHz 단위로 출력합니다.\nESX 게스트 ì „ìš© 하위 명령:\n sessionid: 현재 세션 ID를 출력합니다.\n balloon: 메모리 í’ì„  정보를 출력합니다.\n swap: 메모리 스왑 정보를 출력합니다.\n memlimit: 메모리 제한 정보를 출력합니다.\n memres: 메모리 예약 정보를 출력합니다.\n cpures: CPU 예약 정보를 출력합니다.\n cpulimit: CPU 제한 정보를 출력합니다.\n"
+help.stat = "%1$s: 유용한 게스트 ë° í˜¸ìŠ¤íŠ¸ ì •ë³´ ì¸ì‡„\n사용법: %2$s %3$s <하위 명령>\n\n하위 명령:\n hosttime: 호스트 시간 ì¸ì‡„\n speed: CPU ì†ë„(MHz) ì¸ì‡„\nESX 게스트 ì „ìš© 하위 명령:\n sessionid: 현재 세션 ID ì¸ì‡„\n balloon: 메모리 ë²Œë£¨ë‹ ì •ë³´ ì¸ì‡„\n swap: 메모리 스와핑 ì •ë³´ ì¸ì‡„\n memlimit: 메모리 제한 ì •ë³´ ì¸ì‡„\n memres: 메모리 예약 ì •ë³´ ì¸ì‡„\n cpures: CPU 예약 ì •ë³´ ì¸ì‡„\n cpulimit: CPU 제한 ì •ë³´ ì¸ì‡„\n"
-help.timesync = "%1$s: 게스트 OSì— ëŒ€í•œ 시간 ë™ê¸°í™”를 제어하는 기능\n사용법: %2$s %3$s <하위 명령>\n\n하위 명령:\n enable: 시간 ë™ê¸°í™”ê°€ 사용ë˜ë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤.\n disable: 시간 ë™ê¸°í™”ê°€ 사용ë˜ì§€ ì•Šë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤.\n status: 시간 ë™ê¸°í™” ìƒíƒœë¥¼ 출력합니다.\n"
+help.timesync = "%1$s: 게스트 OSì˜ ì‹œê°„ ë™ê¸°í™” 제어 기능\n사용법: %2$s %3$s <하위 명령>\n\n하위 명령:\n enable: 시간 ë™ê¸°í™” 사용\n disable: 시간 ë™ê¸°í™” 사용 안 함\n status: 시간 ë™ê¸°í™” ìƒíƒœ ì¸ì‡„\n"
help.upgrade = "%1$s: VMware Tools 업그레ì´ë“œì™€ ê´€ë ¨ëœ ê¸°ëŠ¥ìž…ë‹ˆë‹¤.\n사용법: %2$s %3$s <하위 명령> [ì¸ìˆ˜]\n하위 명령:\n status: VMware Tools 업그레ì´ë“œ ìƒíƒœë¥¼ 확ì¸í•©ë‹ˆë‹¤.\n start: VMware Toolsì˜ ìžë™ 업그레ì´ë“œë¥¼ 시작합니다.\n\n업그레ì´ë“œê°€ 수행ë˜ë ¤ë©´ VMware Tools 서비스가 실행ë˜ì–´ì•¼ 합니다.\n"
diff --git a/open-vm-tools/toolbox/l10n/zh_CN.vmsg b/open-vm-tools/toolbox/l10n/zh_CN.vmsg
index f7a83211..316120a9 100644
--- a/open-vm-tools/toolbox/l10n/zh_CN.vmsg
+++ b/open-vm-tools/toolbox/l10n/zh_CN.vmsg
@@ -1,5 +1,5 @@
##########################################################
-# Copyright (C) 2010-2015 VMware, Inc. All rights reserved.
+# Copyright (C) 2010 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
@@ -20,6 +20,12 @@ arg.command = "命令"
arg.devicename = "设备å称"
+arg.logging.level = "日志记录级别"
+
+arg.logging.service = "日志记录æœåŠ¡å"
+
+arg.logging.subcommand = "日志记录æ“作"
+
arg.mountpoint = "挂载点"
arg.scriptpath = "脚本路径"
@@ -38,9 +44,9 @@ disk.shrink.canceled = "ç£ç›˜ç¼©å°å·²å–消。\n"
disk.shrink.complete = "ç£ç›˜ç¼©å°å®Œæˆã€‚\n"
-disk.shrink.conflict = "出错,工具箱认为已å¯ç”¨ç£ç›˜åŽ‹ç¼©ï¼Œè€Œä¸»æœºè®¤ä¸ºå·²ç¦ç”¨ç£ç›˜åŽ‹ç¼©ã€‚\n\n请关闭å†é‡æ–°æ‰“开工具箱,使之与主机åŒæ­¥ã€‚\n"
+disk.shrink.conflict = "错误,工具箱认为已å¯ç”¨ç£ç›˜åŽ‹ç¼©ï¼Œè€Œä¸»æœºè®¤ä¸ºå·²ç¦ç”¨ç£ç›˜åŽ‹ç¼©ã€‚\n\n 请关闭å†é‡æ–°æ‰“开工具箱,以将其与主机åŒæ­¥ã€‚\n"
-disk.shrink.disabled = "该虚拟机的压缩ç£ç›˜åŠŸèƒ½å·²ç¦ç”¨ã€‚\n\n由于链接克隆ã€é“¾æŽ¥å…‹éš†çš„父级ã€\n预分é…ç£ç›˜ã€å¿«ç…§æˆ–其他因素,压缩已ç¦ç”¨ã€‚\n有关详细信æ¯ï¼Œè¯·å‚è§ç”¨æˆ·æ‰‹å†Œã€‚\n"
+disk.shrink.disabled = "为该虚拟机ç¦ç”¨äº†ç£ç›˜åŽ‹ç¼©ã€‚\n\n由于链接的克隆ã€é“¾æŽ¥å…‹éš†çš„父级ã€\n预分é…çš„ç£ç›˜ã€å¿«ç…§æˆ–其他因素,已ç¦ç”¨åŽ‹ç¼©ã€‚\n有关详细信æ¯ï¼Œè¯·å‚è§ç”¨æˆ·æ‰‹å†Œã€‚\n"
disk.shrink.error = "缩å°æ—¶å‡ºçŽ°é”™è¯¯: %1$s\n"
@@ -52,43 +58,45 @@ disk.shrink.partition.notfound = "无法找到分区 %1$s\n"
disk.shrink.partition.unsupported = "分区 %1$s ä¸å¯ç¼©å°\n"
-disk.shrink.unavailable = "压缩功能ä¸å¯ç”¨ï¼Œ\n\nè¿™å¯èƒ½æ˜¯ç”±äºŽæ‚¨æ­£åœ¨è¿è¡Œä½Žç‰ˆæœ¬çš„ VMware 产å“,也å¯èƒ½æ˜¯ç”±äºŽæ‰“开了过多的通信信é“。\n\n如果您正在è¿è¡Œä½Žç‰ˆæœ¬çš„ VMware 产å“,您应该考虑å‡çº§ã€‚\n\n如果打开了过多的通信信é“,您应该é‡æ–°æ‰“开虚拟机电æºã€‚\n"
+disk.shrink.unavailable = "压缩功能ä¸å¯ç”¨ï¼Œ\n\n这是因为您è¿è¡Œè¾ƒä½Žç‰ˆæœ¬çš„ VMware 产å“,或者打开的通信通é“太多。\n\n如果è¿è¡Œçš„是较低版本的 VMware 产å“,应考虑进行å‡çº§ã€‚\n\n如果打开的通信通é“太多,应关闭虚拟机的电æºï¼Œç„¶åŽé‡æ–°æ‰“开虚拟机的电æºã€‚\n"
-disk.shrink.ignoreFreeSpaceWarnings = "请忽略压缩进程期间关于ç£ç›˜ç©ºé—´çš„任何警告。\n"
+disk.shrink.ignoreFreeSpaceWarnings = "请忽略压缩过程期间有关ç£ç›˜ç©ºé—´çš„任何警告。\n"
-disk.wipe.ignoreFreeSpaceWarnings = "请忽略擦除进程期间关于ç£ç›˜ç©ºé—´çš„任何警告。\n"
+disk.wipe.ignoreFreeSpaceWarnings = "请忽略擦除过程期间有关ç£ç›˜ç©ºé—´çš„任何警告。\n"
disk.wiper.error = "错误: %1$s"
disk.wiper.file.error = "错误,无法创建擦除器文件。\n"
-disk.wiper.progress = "\r进度: %1$d"
+disk.wiper.progress = "\r进度:%1$d"
error.missing = "%1$s: 缺失 %2$s\n"
error.noadmin.posix = "%1$s: 您必须是 root 用户æ‰èƒ½æ‰§è¡Œ %2$s æ“作。\n"
-error.noadmin.win = "%1$s: 需è¦æœ‰ç®¡ç†å‘˜æƒé™æ‰èƒ½æ‰§è¡Œ %2$s æ“作。\n使用管ç†å‘˜å‘½ä»¤æ示符完æˆè¿™äº›ä»»åŠ¡ã€‚\n"
+error.noadmin.win = "%1$s: 需è¦å…·æœ‰ç®¡ç†å‘˜æƒé™æ‰èƒ½æ‰§è¡Œ %2$s æ“作。\n请使用管ç†å‘˜å‘½ä»¤æ示符完æˆè¿™äº›ä»»åŠ¡ã€‚\n"
error.novirtual = "%1$s 必须在虚拟机内部è¿è¡Œã€‚\n"
error.unknown = "%1$s: %2$s“%3$sâ€æœªçŸ¥\n"
-help.device = "%1$s: 与虚拟机的硬件设备相关的功能\n用法: %2$s %3$s <å­å‘½ä»¤> [å‚æ•°]\ndev 是设备的å称。\n\nå­å‘½ä»¤:\nenable <设备>: å¯ç”¨è®¾å¤‡ dev\ndisable <设备>: ç¦ç”¨è®¾å¤‡ dev\nlist: 列出所有å¯ç”¨è®¾å¤‡\nstatus <设备>: 打å°è®¾å¤‡çš„状æ€\n"
+help.device = "%1$s: 与虚拟机的硬件设备相关的功能\n用法: %2$s %3$s <å­å‘½ä»¤> [å‚æ•°]\ndev 是设备的å称。\n\nå­å‘½ä»¤:\n enable <dev>: å¯ç”¨è®¾å¤‡ dev\n disable <dev>: ç¦ç”¨è®¾å¤‡ dev\n list: 列出所有å¯ç”¨çš„设备\n status <dev>: 打å°è®¾å¤‡çš„状æ€\n"
-help.disk = "%1$s: 执行ç£ç›˜åŽ‹ç¼©æ“作\n用法: %2$s %3$s <å­å‘½ä»¤> [å‚æ•°]\n\nå­å‘½ä»¤:\n list: 列出å¯ç”¨ä½ç½®\n shrink <ä½ç½®>: 在指定ä½ç½®æ“¦é™¤å’ŒåŽ‹ç¼©æ–‡ä»¶ç³»ç»Ÿ\n shrinkonly: 压缩所有ç£ç›˜\n wipe <ä½ç½®>: 在指定ä½ç½®æ“¦é™¤æ–‡ä»¶ç³»ç»Ÿ\n"
+help.disk = "%1$s: 执行ç£ç›˜åŽ‹ç¼©æ“作\n用法: %2$s %3$s <å­å‘½ä»¤> [å‚æ•°]\n\nå­å‘½ä»¤:\n list: 列出å¯ç”¨çš„ä½ç½®\n shrink <ä½ç½®>: 擦除并压缩指定ä½ç½®çš„文件系统\n shrinkonly: 压缩所有ç£ç›˜\n wipe <ä½ç½®>: 擦除指定ä½ç½®çš„文件系统\n"
help.hint = "有关详细信æ¯ï¼Œè¯·å°è¯•â€œ%1$s %2$s%3$s%4$sâ€ã€‚\n"
-help.main = "用法: %1$s <命令> [选项] [å­å‘½ä»¤]\n键入“%2$s %3$s <命令>â€ä»¥èŽ·å–有关特定命令的帮助。\n键入“%4$s -vâ€æŸ¥çœ‹ VMware Tools 版本。\n使用“-qâ€é€‰é¡¹å¯å–消 stdout 输出。\n大多数命令都有å­å‘½ä»¤ã€‚\n\nå¯ç”¨å‘½ä»¤:\n device\n disk\n script\n stat\n timesync\n upgrade (并éžæ‰€æœ‰æ“作系统都支æŒ)\n"
+help.logging = ""%1$s: 修改 Tools 日志记录\n用法: %2$s %3$s level <å­å‘½ä»¤> <æœåŠ¡å> <级别>\n\nå­å‘½ä»¤:\n get <æœåŠ¡å>: 显示当å‰çº§åˆ«\n set <æœåŠ¡å> <级别>: 设置当å‰çº§åˆ«\n\n<æœåŠ¡å> å¯ä»¥æ˜¯å—支æŒçš„任何æœåŠ¡ï¼ŒåŒ…括 vmsvc 或 vmusr\n<级别> å¯ä»¥æ˜¯ errorã€criticalã€warningã€infoã€message 或 debug 中的一ç§\n 默认为 %4$s\n""
+
+help.main = "用法:%1$s <命令> [选项] [å­å‘½ä»¤]\n键入“%2$s %3$s <命令>â€ä»¥èŽ·å–特定命令的帮助。\n键入“%4$s -vâ€ä»¥æŸ¥çœ‹ VMware Tools 版本。\n使用“-qâ€é€‰é¡¹ä»¥ç¦ç”¨æ ‡å‡†è¾“出。\n大多数命令具有å­å‘½ä»¤ã€‚\n\nå¯ç”¨çš„命令:\n device\n disk\n logging\n script\n stat\n timesync\n upgrade (并éžé€‚用于所有æ“作系统)\n"
-help.script = "%1$s: 控制脚本è¿è¡Œä»¥å“应打开电æºæ“作\n用法: %2$s %3$s <power|resume|suspend|shutdown> <å­å‘½ä»¤> [å‚æ•°]\n\nå­å‘½ä»¤:\n enable: å¯ç”¨ç»™å®šè„šæœ¬ï¼Œå¹¶å°†å…¶è·¯å¾„还原为默认值\n disable: ç¦ç”¨ç»™å®šè„šæœ¬\n set <完整路径>: 将给定脚本设置为给定路径\n default: 打å°ç»™å®šè„šæœ¬çš„默认路径\n current: 打å°ç»™å®šè„šæœ¬çš„当å‰è·¯å¾„\n"
+help.script = "%1$s: 控制脚本è¿è¡Œä»¥å“应打开电æºæ“作\n用法: %2$s %3$s <power|resume|suspend|shutdown> <å­å‘½ä»¤> [å‚æ•°]\n\nå­å‘½ä»¤:\n enable: å¯ç”¨ç»™å®šè„šæœ¬ï¼Œå¹¶å°†å…¶è·¯å¾„æ¢å¤ä¸ºé»˜è®¤å€¼\n disable: ç¦ç”¨ç»™å®šè„šæœ¬\n set <完整路径>: 将给定脚本设置为给定路径\n default: 打å°ç»™å®šè„šæœ¬çš„默认路径\n current: 打å°ç»™å®šè„šæœ¬çš„当å‰è·¯å¾„\n"
-help.stat = "%1$s: 打å°æœ‰ç”¨çš„客户机和主机信æ¯\n用法: %2$s %3$s <å­å‘½ä»¤>\n\nå­å‘½ä»¤:\n hosttime: 打å°ä¸»æœºæ—¶é—´\n speed: 以 MHz 为å•ä½æ‰“å° CPU 速度\n ä»… ESX 客户机å­å‘½ä»¤:\n sessionid: 打å°å½“å‰çš„ä¼šè¯ ID\n balloon: 打å°å†…存虚拟增长信æ¯\n swap: 打å°å†…存交æ¢ä¿¡æ¯\n memlimit: 打å°å†…å­˜é™åˆ¶ä¿¡æ¯\n memres: 打å°å†…存预留信æ¯\n cpures: æ‰“å° CPU 预留信æ¯\n cpulimit: æ‰“å° CPU é™åˆ¶ä¿¡æ¯\n"
+help.stat = "%1$s: 打å°æœ‰ç”¨çš„æ¥å®¾å’Œä¸»æœºä¿¡æ¯\n用法: %2$s %3$s <å­å‘½ä»¤>\n\nå­å‘½ä»¤:\n hosttime: 打å°ä¸»æœºæ—¶é—´\n speed: æ‰“å° CPU 速度(以 MHz 为å•ä½)\nä»… ESX æ¥å®¾å­å‘½ä»¤:\n sessionid: 打å°å½“å‰ä¼šè¯ id\n balloon: 打å°å†…存扩大信æ¯\n swap: 打å°å†…存交æ¢ä¿¡æ¯\n memlimit: 打å°å†…å­˜é™åˆ¶ä¿¡æ¯\n memres: 打å°å†…å­˜ä¿ç•™ä¿¡æ¯\n cpures: æ‰“å° CPU ä¿ç•™ä¿¡æ¯\n cpulimit: æ‰“å° CPU é™åˆ¶ä¿¡æ¯\n"
-help.timesync = "%1$s: 用于控制客户机æ“作系统上的时间åŒæ­¥çš„功能\n用法: %2$s %3$s <å­å‘½ä»¤>\n\nå­å‘½ä»¤:\n enable: å¯ç”¨æ—¶é—´åŒæ­¥\n disable: ç¦ç”¨æ—¶é—´åŒæ­¥\n status: 打å°æ—¶é—´åŒæ­¥çŠ¶æ€\n"
+help.timesync = "%1$s: 用于控制æ¥å®¾æ“作系统上的时间åŒæ­¥çš„功能\n用法: %2$s %3$s <å­å‘½ä»¤>\n\nå­å‘½ä»¤:\n enable: å¯ç”¨æ—¶é—´åŒæ­¥\n disable: ç¦ç”¨æ—¶é—´åŒæ­¥\n status: 打å°æ—¶é—´åŒæ­¥çŠ¶æ€\n"
-help.upgrade = "%1$s: 与å‡çº§ VMware Tools 相关的功能。\n用法: %2$s %3$s <å­å‘½ä»¤> [å‚æ•°]\nå­å‘½ä»¤:\n status: 检查 VMware Tools å‡çº§çŠ¶æ€ã€‚\n start: å¯åŠ¨ VMware Tools 自动å‡çº§ã€‚\n\nè¦è¿›è¡Œå‡çº§ï¼Œéœ€è¦è¿è¡Œ VMware Tools æœåŠ¡ã€‚\n"
+help.upgrade = "%1$s: 与å‡çº§ VMware Tools 相关的功能。\n用法: %2$s %3$s <å­å‘½ä»¤> [å‚æ•°]\nå­å‘½ä»¤:\n status: 检查 VMware Tools å‡çº§çŠ¶æ€ã€‚\n start: å¯åŠ¨ VMware Tools 自动å‡çº§ã€‚\n\nè¦ä½¿å‡çº§æ­£å¸¸è¿›è¡Œï¼Œéœ€è¦è¿è¡Œ VMware Tools æœåŠ¡ã€‚\n"
option.disabled = "å·²ç¦ç”¨"
diff --git a/open-vm-tools/toolbox/toolbox-cmd.c b/open-vm-tools/toolbox/toolbox-cmd.c
index 55bddb77..e8b50ed2 100644
--- a/open-vm-tools/toolbox/toolbox-cmd.c
+++ b/open-vm-tools/toolbox/toolbox-cmd.c
@@ -106,6 +106,7 @@ static CmdTable commands[] = {
#if (defined(_WIN32) || defined(linux)) && !defined(OPEN_VM_TOOLS)
{ "upgrade", Upgrade_Command, TRUE, TRUE, Upgrade_Help},
#endif
+ { "logging", Logging_Command, TRUE, TRUE, Logging_Help},
{ "help", HelpCommand, FALSE, FALSE, ToolboxCmdHelp},
};
@@ -294,6 +295,7 @@ ToolboxCmdHelp(const char *progName, // IN
"Available commands:\n"
" device\n"
" disk\n"
+ " logging\n"
" script\n"
" stat\n"
" timesync\n"
diff --git a/open-vm-tools/toolbox/toolboxCmdInt.h b/open-vm-tools/toolbox/toolboxCmdInt.h
index 1008e038..d52d9e00 100644
--- a/open-vm-tools/toolbox/toolboxCmdInt.h
+++ b/open-vm-tools/toolbox/toolboxCmdInt.h
@@ -127,6 +127,7 @@ DECLARE_COMMAND(Disk);
DECLARE_COMMAND(Script);
DECLARE_COMMAND(Stat);
DECLARE_COMMAND(TimeSync);
+DECLARE_COMMAND(Logging);
#if defined(_WIN32) || (defined(linux) && !defined(OPEN_VM_TOOLS))
DECLARE_COMMAND(Upgrade);
diff --git a/open-vm-tools/toolbox/toolboxcmd-logging.c b/open-vm-tools/toolbox/toolboxcmd-logging.c
new file mode 100644
index 00000000..69e1c05b
--- /dev/null
+++ b/open-vm-tools/toolbox/toolboxcmd-logging.c
@@ -0,0 +1,286 @@
+/*********************************************************
+ * Copyright (C) 2015 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * toolboxcmd-logging.c --
+ *
+ * Various logging operations for toolbox-cmd.
+ *
+ * Note:
+ * Servicenames are not sanity checked. This means it can report
+ * the default value for a bogus servicename, or setting values for
+ * an unsupported servicename. But any sanity checking would require
+ * all possible servicenames to #define themselves. Lack of
+ * a sanity check overrrides this complexity.
+ *
+ * TODO: This currently just modifies the tools.conf file, which means
+ * that if tools is running, it can talke up to 5 seconds to react
+ * to any changes. It would be better if toolsd could be poked to
+ * shrink that delay.
+ */
+
+#include <time.h>
+
+#include "conf.h"
+#include "toolboxCmdInt.h"
+#include "vmware/tools/i18n.h"
+#include "vmware/tools/utils.h"
+#include "vmware/tools/log.h"
+
+#define LOGGING_CONF_SECTION "logging"
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * LoggingCheckLevel --
+ *
+ * Sanity check logging level.
+ *
+ * Results:
+ * Returns TRUE if its a valid logging level, FALSE if not.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static gboolean
+LoggingCheckLevel(char *level) // logging level
+{
+ if ((strcmp("error", level) == 0) ||
+ (strcmp("critical", level) == 0) ||
+ (strcmp("warning", level) == 0) ||
+ (strcmp("message", level) == 0) ||
+ (strcmp("info", level) == 0) ||
+ (strcmp("debug", level) == 0)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * LoggingSetLevel --
+ *
+ * Set logging level
+ *
+ * Results:
+ * Returns EXIT_SUCCESS on success.
+ * Returns the appropriate exit codes on errors.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+LoggingSetLevel(char *service, // service
+ char *level) // logging level
+{
+ GKeyFile *confDict = NULL;
+ gchar *confName;
+ GError *err = NULL;
+ int ret = EXIT_SUCCESS;
+
+ VMTools_LoadConfig(NULL,
+ G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
+ &confDict,
+ NULL);
+
+ if (confDict == NULL) {
+ confDict = g_key_file_new();
+ }
+
+ confName = g_strdup_printf("%s.level", service);
+
+ g_key_file_set_string(confDict, LOGGING_CONF_SECTION,
+ confName, level);
+
+ if (!VMTools_WriteConfig(NULL, confDict, &err)) {
+ ToolsCmd_PrintErr(SU_(script.write.error, "Error writing config: %s\n"),
+ err->message);
+ g_clear_error(&err);
+ ret = EX_TEMPFAIL;
+ }
+
+ g_key_file_free(confDict);
+ g_free(confName);
+
+ return ret;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * LoggingGetLevel --
+ *
+ * Get current logging level
+ *
+ * Results:
+ * Returns EXIT_SUCCESS on success.
+ * Returns the appropriate exit codes on errors.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+LoggingGetLevel(char *service) // service
+{
+ GKeyFile *confDict = NULL;
+ gchar *confName;
+ int ret = EXIT_SUCCESS;
+ gchar *level;
+
+ VMTools_LoadConfig(NULL,
+ G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
+ &confDict,
+ NULL);
+
+ if (confDict == NULL) {
+ confDict = g_key_file_new();
+ }
+
+ confName = g_strdup_printf("%s.level", service);
+
+ level = g_key_file_get_string(confDict, LOGGING_CONF_SECTION,
+ confName, NULL);
+
+ if (level) {
+ g_print("%s = %s\n", confName, level);
+ } else {
+ g_print("%s = %s\n", confName, VMTOOLS_LOGGING_LEVEL_DEFAULT);
+ }
+ g_key_file_free(confDict);
+ g_free(confName);
+ g_free(level);
+
+ return ret;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Logging_Command --
+ *
+ * Handle and parse logging commands.
+ *
+ * Results:
+ * Returns EXIT_SUCCESS on success.
+ * Returns the appropriate exit codes on errors.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+Logging_Command(char **argv, // IN: Command line arguments
+ int argc, // IN: Length of command line arguments
+ gboolean quiet) // IN
+{
+ char *subcommand = argv[optind];
+ char *op;
+
+ if ((optind + 1) >= argc) {
+ ToolsCmd_MissingEntityError(argv[0],
+ SU_(arg.logging.subcommand, "logging operation"));
+ return EX_USAGE;
+ }
+ if ((optind + 2) >= argc) {
+ ToolsCmd_MissingEntityError(argv[0],
+ SU_(arg.logging.service, "logging servicename"));
+ return EX_USAGE;
+ }
+
+ op = argv[optind + 1];
+
+ if (toolbox_strcmp(subcommand, "level") == 0) {
+ if (toolbox_strcmp(op, "set") == 0) {
+ if ((optind + 3) >= argc) {
+ ToolsCmd_MissingEntityError(argv[0],
+ SU_(arg.logging.level, "logging level"));
+ return EX_USAGE;
+ } else {
+ if (!LoggingCheckLevel(argv[optind + 3])) {
+ ToolsCmd_UnknownEntityError(argv[0],
+ SU_(arg.logging.level, "logging level"),
+ argv[optind + 3]);
+ return EX_USAGE;
+ }
+ return LoggingSetLevel(argv[optind + 2], argv[optind + 3]);
+ }
+ } else if (toolbox_strcmp(op, "get") == 0) {
+ return LoggingGetLevel(argv[optind + 2]);
+ } else {
+ ToolsCmd_UnknownEntityError(argv[0],
+ SU_(arg.subcommand, "subcommand"),
+ argv[optind + 1]);
+ return EX_USAGE;
+ }
+ } else {
+ ToolsCmd_UnknownEntityError(argv[0],
+ SU_(arg.subcommand, "subcommand"),
+ argv[optind]);
+ return EX_USAGE;
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Logging_Help --
+ *
+ * Prints the help for the logging command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Logging_Help(const char *progName, // IN: The name of the program obtained from argv[0]
+ const char *cmd) // IN
+{
+ g_print(SU_(help.logging,
+ "%s: modify tools logging\n"
+ "Usage: %s %s level <subcommand> <servicename> <level>\n\n"
+ "Subcommands:\n"
+ " get <servicename>: display current level\n"
+ " set <servicename> <level>: set current level\n\n"
+ "<servicename> can be any supported service, such as vmsvc or vmusr\n"
+ "<level> can be one of error, critical, warning, info, message, debug\n"
+ " default is %s\n"),
+ cmd, progName, cmd, VMTOOLS_LOGGING_LEVEL_DEFAULT);
+}
+
diff --git a/open-vm-tools/toolbox/toolboxcmd-shrink.c b/open-vm-tools/toolbox/toolboxcmd-shrink.c
index 2f789e17..5b0ab02d 100644
--- a/open-vm-tools/toolbox/toolboxcmd-shrink.c
+++ b/open-vm-tools/toolbox/toolboxcmd-shrink.c
@@ -462,6 +462,7 @@ ShrinkDoWipeAndShrink(char *mountPoint, // IN: mount point
#endif
rc = EXIT_SUCCESS;
+ g_print("\n");
if (progress >= 100 && performShrink) {
rc = ShrinkDiskSendRPC();
} else if (progress < 100) {
diff --git a/open-vm-tools/vgauth/cli/l10n/de.vmsg b/open-vm-tools/vgauth/cli/l10n/de.vmsg
index 30e04775..637f5ca0 100644
--- a/open-vm-tools/vgauth/cli/l10n/de.vmsg
+++ b/open-vm-tools/vgauth/cli/l10n/de.vmsg
@@ -16,62 +16,60 @@
#
##########################################################
-addsubj.fail = "%1$s: Fehler beim Hinzufügen eines Alias für Benutzer '%2$s': %3$s.\n"
+addsubj.fail = "%1$s: Das Hinzufügen des Alias für den Benutzer '%2$s': %3$s ist fehlgeschlagen.\n"
addsubj.success = "%1$s: Alias hinzugefügt\n"
-addoptions.comment = "Betreff Kommentar"
+addoptions.comment = "Inhaberkommentar"
-addoptions.file = "Name der PEM-Datei"
+addoptions.file = "PEM-Dateiname"
-addoptions.global = "Zertifikat zur globalen Zuordnungsdatei hinzufügen"
+addoptions.global = "Zertifikat der globalen Zuordnungsdatei hinzufügen"
-addoptions.subject = "SAML-Betreff"
+addoptions.subject = "Der SAML-Inhaber"
-addoptions.username = "Benutzer, in dessen Zertifikatspeicher Hinzufügung erfolgt"
+addoptions.username = "Benutzer, dessen Zertifikatsspeicher hinzugefügt wird zu"
-addoptions.verbose = "Ausführlicher Vorgang"
+addoptions.verbose = "Detaillierter Vorgang"
-cmdline.parse = "Fehler beim Parsen der Befehlszeile"
+cmdline.parse = "Die Analyse der Befehlszeile ist fehlgeschlagen"
cmdline.summary.pemfile = "PEM-Datei"
-cmdline.summary.subject = "Betreff"
+cmdline.summary.subject = "Inhaber"
cmdline.summary.username = "Benutzername"
cmdline.summary.comm = "Kommentar"
list.comment = "Kommentar"
-list.count = "%1$s Gefunden: %2$d Aliase für Benutzer '%3$s'\n"
+list.count = "%1$s: Es wurden %2$d Aliase für den Benutzer '%3$s' gefunden.\n"
-list.error = "%1$s: Fehler beim Auflisten von Aliasen für Benutzer '%2$s': %3$s.\n"
-list.subject = "Betreff"
+list.error = "%1$s: Die Auflistung der Aliase für den Benutzer '%2$s': %3$s ist fehlgeschlagen.\n"
+list.subject = "Inhaber"
-listmapped.count = "%1$s Gefunden: %2$d zugeordnete Aliase\n"
+listmapped.count = "%1$s: Es wurden %2$d zugeordnete Aliase gefunden.\n"
-listmapped.error = "%1$s: Fehler beim Auflisten von zugeordneten Aliasen: %2$s.\n"
+listmapped.error = "%1$s: Die Auflistung der zugeordneten Aliase %2$s ist fehlgeschlagen.\n"
-listmapped.subject = "Betreff"
+listmapped.subject = "Inhaber"
listmapped.username = "Benutzername"
-listoptions.username =
- "Benutzer, dessen Zertifikatspeicher abgefragt wird"
+listoptions.username = "Benutzer, dessen Zertifikatsspeicher abgefragt wird"
-listoptions.verbose = "Ausführlicher Vorgang"
+listoptions.verbose = "Detaillierter Vorgang"
-loadfile.fail = "%1$s: Fehler beim Lesen von PEM-Datei '%2$s'\n"
+loadfile.fail = "%1$s: PEM-Datei '%2$s' kann nicht gelesen werden\n"
name.any = "<ALLE>"
-removesubj.fail = "%1$s: Fehler beim Löschen eines Alias für Benutzer '%2$s': %3$s.\n"
+removesubj.fail = "%1$s: Das Entfernen des Alias für den Benutzer '%2$s': %3$s ist fehlgeschlagen.\n"
-removesubj.success = "%1$s: Alias gelöscht\n"
+removesubj.success = "%1$s: Alias entfernt\n"
-removeoptions.file = "Name der PEM-Datei"
+removeoptions.file = "PEM-Dateiname"
-removeoptions.subject = "SAML-Betreff"
-removeoptions.username =
- "Benutzer, in dessen Zertifikatspeicher Löschvorgang erfolgt"
+removeoptions.subject = "Der SAML-Inhaber"
+removeoptions.username = "Benutzer, dessen Zertifikatsspeicher entfernt wurde aus"
-removeoptions.verbose = "Ausführlicher Vorgang"
+removeoptions.verbose = "Detaillierter Vorgang"
-vgauth.init.failed = "Fehler beim Initialisieren von VGAuth"
+vgauth.init.failed = "Die Initialisierung von VGAuth ist fehlgeschlagen"
diff --git a/open-vm-tools/vgauth/cli/l10n/es.vmsg b/open-vm-tools/vgauth/cli/l10n/es.vmsg
index ad0e33f4..df21665c 100644
--- a/open-vm-tools/vgauth/cli/l10n/es.vmsg
+++ b/open-vm-tools/vgauth/cli/l10n/es.vmsg
@@ -16,8 +16,8 @@
#
##########################################################
-addsubj.fail = "%1$s: No ha podido añadirse el alias del usuario '%2$s': %3$s.\n"
-addsubj.success = "%1$s: se ha añadido el alias\n"
+addsubj.fail = "%1$s: No se pudo agregar el alias del usuario '%2$s': %3$s.\n"
+addsubj.success = "%1$s: alias agregado\n"
addoptions.comment = "comentario del tema"
@@ -42,35 +42,33 @@ cmdline.summary.comm = "comentario"
list.comment = "Comentario"
list.count = "%1$s Se han encontrado %2$d alias para el usuario '%3$s'\n"
-list.error = "%1$s: No se han podido listar los alias del usuario '%2$s': %3$s.\n"
+list.error = "%1$s: No se pudieron enumerar los alias del usuario '%2$s': %3$s.\n"
list.subject = "Asunto"
listmapped.count = "%1$s Se han encontrado %2$d alias asignados\n"
-listmapped.error = "%1$s: No se han podido listar los alias asignados: %2$s.\n"
+listmapped.error = "%1$s: No se pudieron enumerar los alias asignados: %2$s.\n"
listmapped.subject = "Asunto"
listmapped.username = "Nombre de usuario"
-listoptions.username =
- "El usuario cuyo almacén de certificados se está consultando"
+listoptions.username = "El usuario cuyo almacén de certificados se está consultando"
listoptions.verbose = "Operación detallada"
-loadfile.fail = "%1$s: No se ha podido leer el archivo PEM '%2$s'\n"
+loadfile.fail = "%1$s: No se puede leer el archivo PEM '%2$s'\n"
name.any = "<CUALQUIERA>"
-removesubj.fail = "%1$s: No se ha podido eliminar el alias del usuario '%2$s': %3$s.\n"
+removesubj.fail = "%1$s: No se pudo quitar el alias del usuario '%2$s': %3$s.\n"
-removesubj.success = "%1$s: alias eliminado\n"
+removesubj.success = "%1$s: alias quitado\n"
removeoptions.file = "nombre de archivo PEM"
removeoptions.subject = "Tema de SAML"
-removeoptions.username =
- "El usuario cuyo almacén de certificados se está eliminando de"
+removeoptions.username = "El usuario cuyo almacén de certificados se está eliminando de"
removeoptions.verbose = "Operación detallada"
diff --git a/open-vm-tools/vgauth/cli/l10n/fr.vmsg b/open-vm-tools/vgauth/cli/l10n/fr.vmsg
index d1d7d789..d7e6d82a 100644
--- a/open-vm-tools/vgauth/cli/l10n/fr.vmsg
+++ b/open-vm-tools/vgauth/cli/l10n/fr.vmsg
@@ -16,62 +16,60 @@
#
##########################################################
-addsubj.fail = "%1$s : Échec de l'ajout de l'alias pour l'utilisateur '%2$s' : %3$s.\n"
-addsubj.success = "%1$s : alias ajouté\n"
+addsubj.fail = "%1$s : échec de l'ajout de l'alias pour l'utilisateur '%2$s' : %3$s.\n"
+addsubj.success = "%1$s : alias ajouté\n"
-addoptions.comment = "commentaire de l'objet"
+addoptions.comment = "commentaire sur le sujet"
-addoptions.file = "Nom du fichier PEM"
+addoptions.file = "Nom de fichier PEM"
addoptions.global = "Ajouter le certificat au fichier de mappage global"
-addoptions.subject = "L'objet SAML"
+addoptions.subject = "Le sujet SAML"
-addoptions.username = "Utilisateur dont le magasin de certificats est en train d'être ajouté"
+addoptions.username = "Utilisateur dont le magasin de certificats est ajouté à"
-addoptions.verbose = "Opération détaillée"
+addoptions.verbose = "Opération en mode détaillé"
-cmdline.parse = "Échec de l'analyse de ligne de commande"
+cmdline.parse = "Échec de l'analyse de la ligne de commande"
cmdline.summary.pemfile = "Fichier PEM"
-cmdline.summary.subject = "objet"
+cmdline.summary.subject = "sujet"
cmdline.summary.username = "nom d'utilisateur"
cmdline.summary.comm = "commentaire"
list.comment = "Commentaire"
-list.count = "%1$s A trouvé %2$d alias pour l'utilisateur '%3$s'\n"
+list.count = "%1$s a trouvé %2$d alias pour l'utilisateur '%3$s'\n"
-list.error = "%1$s : impossible de lister les alias pour l'utilisateur '%2$s' : %3$s.\n"
-list.subject = "Objet"
+list.error = "%1$s : échec de la création de la liste d'alias pour l'utilisateur '%2$s' : %3$s.\n"
+list.subject = "Sujet"
-listmapped.count = "%1$s A trouvé %2$d alias mappés\n"
+listmapped.count = "%1$s a trouvé %2$d alias mappés\n"
-listmapped.error = "%1$s : impossible de lister les alias mappés : %2$s.\n"
+listmapped.error = "%1$s : échec de la création de la liste d'alias mappés : %2$s.\n"
-listmapped.subject = "Objet"
+listmapped.subject = "Sujet"
listmapped.username = "Nom d'utilisateur"
-listoptions.username =
- "Utilisateur dont le magasin de certificats est en cours d'interrogation"
+listoptions.username = "Utilisateur dont le magasin de certificats est interrogé"
-listoptions.verbose = "Opération détaillée"
+listoptions.verbose = "Opération en mode détaillé"
-loadfile.fail = "%1$s : impossible de lire le fichier PEM '%2$s'\n"
+loadfile.fail = "%1$s : impossible de lire le fichier PEM '%2$s'\n"
-name.any = "<ANY>"
+name.any = "<QUELCONQUE>"
-removesubj.fail = "%1$s : impossible de supprimer l'alias pour l'utilisateur '%2$s' : %3$s.\n"
+removesubj.fail = "%1$s : échec de la suppression de l'alias pour l'utilisateur '%2$s' : %3$s.\n"
-removesubj.success = "%1$s : alias supprimé\n"
+removesubj.success = "%1$s : alias supprimé\n"
-removeoptions.file = "Nom du fichier PEM"
+removeoptions.file = "Nom de fichier PEM"
-removeoptions.subject = "L'objet SAML"
-removeoptions.username =
- "Utilisateur dont le magasin de certificat est en cours de suppression"
+removeoptions.subject = "Le sujet SAML"
+removeoptions.username = "Utilisateur dont le magasin de certificats est supprimé de"
-removeoptions.verbose = "Opération détaillée"
+removeoptions.verbose = "Opération en mode détaillé"
vgauth.init.failed = "Échec de l'initialisation de VGAuth"
diff --git a/open-vm-tools/vgauth/cli/l10n/it.vmsg b/open-vm-tools/vgauth/cli/l10n/it.vmsg
index a84e2a2b..014f8334 100644
--- a/open-vm-tools/vgauth/cli/l10n/it.vmsg
+++ b/open-vm-tools/vgauth/cli/l10n/it.vmsg
@@ -16,7 +16,7 @@
#
##########################################################
-addsubj.fail = "%1$s: Impossibile aggiungere alias per l'utente "%2$s": %3$s.\n"
+addsubj.fail = "%1$s: Impossibile aggiungere alias per l'utente '%2$s': %3$s.\n"
addsubj.success = "%1$s: alias aggiunto\n"
addoptions.comment = "commento oggetti"
@@ -40,37 +40,35 @@ cmdline.summary.username = "nome utente"
cmdline.summary.comm = "commento"
list.comment = "Commento"
-list.count = "%1$s Trovati %2$d alias per l'utente "%3$s"\n"
+list.count = "%1$s Trovati %2$d alias per l'utente '%3$s'\n"
-list.error = "%1$s: Impossibile elencare gli alias per l'utente "%2$s": %3$s.\n"
+list.error = "%1$s: Impossibile elencare gli alias per l'utente '%2$s': %3$s.\n"
list.subject = "Oggetto"
listmapped.count = "%1$s Trovati %2$d alias mappati\n"
-listmapped.error = "%1$s: Impossibile elencare gli alias mappati: %2$s.\n"
+listmapped.error = "%1$s: Impossibile elencare gli alias mappati:%2$s.\n"
listmapped.subject = "Oggetto"
listmapped.username = "Nome utente"
-listoptions.username =
- "Utente il cui archivio certificati viene interrogato"
+listoptions.username = "Utente il cui archivio certificati viene interrogato"
listoptions.verbose = "Operazione Verbose"
-loadfile.fail = "%1$s: Impossibile leggere il file PEM "%2$s"\n"
+loadfile.fail = "%1$s: Impossibile leggere il file PEM '%2$s'\n"
name.any = "<QUALSIASI>"
-removesubj.fail = "%1$s: Impossibile rimuovere l'alias per l'utente "%2$s": %3$s.\n"
+removesubj.fail = "%1$s: Impossibile rimuovere l'alias per l'utente '%2$s': %3$s.\n"
removesubj.success = "%1$s: alias rimosso\n"
removeoptions.file = "Nome file PEM"
removeoptions.subject = "L'oggetto SAML"
-removeoptions.username =
- "L'utente da cui viene rimosso l'archivio certificati"
+removeoptions.username = "L'utente da cui viene rimosso l'archivio certificati"
removeoptions.verbose = "Operazione Verbose"
diff --git a/open-vm-tools/vgauth/cli/l10n/ja.vmsg b/open-vm-tools/vgauth/cli/l10n/ja.vmsg
index 89051602..21b31250 100644
--- a/open-vm-tools/vgauth/cli/l10n/ja.vmsg
+++ b/open-vm-tools/vgauth/cli/l10n/ja.vmsg
@@ -16,62 +16,60 @@
#
##########################################################
-addsubj.fail = "%1$s: ユーザー 「%2$sã€ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’追加ã§ãã¾ã›ã‚“ã§ã—ãŸ: %3$s。\n"
-addsubj.success = "%1$s: 追加ã•ã‚ŒãŸã‚¨ã‚¤ãƒªã‚¢ã‚¹\n"
+addsubj.fail = "%1$s: ユーザー '%2$s' ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’追加ã§ãã¾ã›ã‚“ã§ã—ãŸ: %3$s。\n"
+addsubj.success = "%1$s: エイリアスãŒè¿½åŠ ã•ã‚Œã¾ã—ãŸ\n"
-addoptions.comment = "件åコメント"
+addoptions.comment = "サブジェクトã®ã‚³ãƒ¡ãƒ³ãƒˆ"
addoptions.file = "PEM ファイルå"
-addoptions.global = "グローãƒãƒ« マッピング ファイルã«è¨¼æ˜Žæ›¸ã‚’追加ã—ã¾ã™"
+addoptions.global = "グローãƒãƒ« マッピング ファイルã«è¨¼æ˜Žæ›¸ã‚’追加"
-addoptions.subject = "SAML 件å"
+addoptions.subject = "SAML サブジェクト"
-addoptions.username = "証明書ストアãŒè¿½åŠ ã•ã‚Œã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼"
+addoptions.username = "証明書ストアãŒè¿½åŠ ã•ã‚Œã¦ã„るユーザー"
-addoptions.verbose = "冗長æ“作"
+addoptions.verbose = "詳細ãªæ“作"
-cmdline.parse = "コマンド行ã®è§£æžãŒå¤±æ•—ã—ã¾ã—ãŸ"
+cmdline.parse = "コマンド ラインã®è§£æžã«å¤±æ•—ã—ã¾ã—ãŸ"
cmdline.summary.pemfile = "PEM ファイル"
-cmdline.summary.subject = "件å"
-cmdline.summary.username = "username"
+cmdline.summary.subject = "サブジェクト"
+cmdline.summary.username = "ユーザーå"
cmdline.summary.comm = "コメント"
list.comment = "コメント"
-list.count = "%1$s ユーザー「%3$sã€ã® %2$d エイリアスãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ\n"
+list.count = "%1$s ã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ '%3$s' ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãŒ %2$d 個検出ã•ã‚Œã¾ã—ãŸ\n"
-list.error = "%1$s: ユーザー「%2$sã€ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’リストã§ãã¾ã›ã‚“ã§ã—ãŸ: %3$s。\n"
-list.subject = "件å"
+list.error = "%1$s: ユーザー '%2$s' ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’一覧表示ã§ãã¾ã›ã‚“ã§ã—ãŸ: %3$s。\n"
+list.subject = "サブジェクト"
-listmapped.count = "%1$s %2$d ã®ãƒžãƒƒãƒ—済ã¿ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ\n"
+listmapped.count = "%1$s ã§ãƒžãƒƒãƒ—ã•ã‚ŒãŸ %2$d 個ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ\n"
-listmapped.error = "%1$s: マップ済ã¿ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’リストã§ãã¾ã›ã‚“ã§ã—ãŸ: %2$s。\n"
+listmapped.error = "%1$s: マップã•ã‚ŒãŸã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’一覧表示ã§ãã¾ã›ã‚“ã§ã—ãŸ: %2$s。\n"
-listmapped.subject = "件å"
+listmapped.subject = "サブジェクト"
listmapped.username = "ユーザーå"
-listoptions.username =
- "証明書ストアãŒã‚¯ã‚¨ãƒªã•ã‚Œã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼"
+listoptions.username = "証明書ストアãŒç…§ä¼šã•ã‚Œã¦ã„るユーザー"
-listoptions.verbose = "冗長æ“作"
+listoptions.verbose = "詳細ãªæ“作"
-loadfile.fail = "%1$s: PEM ファイル「%2$sã€ã‚’読ã¿å–ã‚Œã¾ã›ã‚“\n"
+loadfile.fail = "%1$s: PEM ファイル '%2$s' を読ã¿å–ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“\n"
-name.any = "<ä»»æ„>"
+name.any = "<ANY>"
-removesubj.fail = "%1$s: ユーザー「%2$sã€ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’削除ã§ãã¾ã›ã‚“ã§ã—ãŸ: %3$s。\n"
+removesubj.fail = "%1$s: ユーザー '%2$s' ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’削除ã§ãã¾ã›ã‚“ã§ã—ãŸ: %3$s。\n"
-removesubj.success = "%1$s: 削除ã•ã‚ŒãŸã‚¨ã‚¤ãƒªã‚¢ã‚¹\n"
+removesubj.success = "%1$s: エイリアスãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸ\n"
removeoptions.file = "PEM ファイルå"
-removeoptions.subject = "SAML 件å"
-removeoptions.username =
- "証明書ストアãŒå‰Šé™¤ã•ã‚Œã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼"
+removeoptions.subject = "SAML サブジェクト"
+removeoptions.username = "証明書ストアãŒå‰Šé™¤ã•ã‚Œã¦ã„るユーザー"
-removeoptions.verbose = "冗長æ“作"
+removeoptions.verbose = "詳細ãªæ“作"
vgauth.init.failed = "VGAuth ã‚’åˆæœŸåŒ–ã§ãã¾ã›ã‚“ã§ã—ãŸ"
diff --git a/open-vm-tools/vgauth/cli/l10n/ko.vmsg b/open-vm-tools/vgauth/cli/l10n/ko.vmsg
index a27f9ddd..67662548 100644
--- a/open-vm-tools/vgauth/cli/l10n/ko.vmsg
+++ b/open-vm-tools/vgauth/cli/l10n/ko.vmsg
@@ -16,62 +16,60 @@
#
##########################################################
-addsubj.fail = "%1$s: '%2$s' 사용ìžì— 대한 ë³„ì¹­ì„ ì¶”ê°€í•˜ì§€ 못했습니다. %3$s.\n"
-addsubj.success = "%1$s: ë³„ì¹­ì´ ì¶”ê°€ë˜ì—ˆìŠµë‹ˆë‹¤.\n"
+addsubj.fail = "%1$s: ì‚¬ìš©ìž '%2$s'ì— ëŒ€í•œ ë³„ì¹­ì„ ì¶”ê°€í•˜ì§€ 못했습니다. %3$s.\n"
+addsubj.success = "%1$s: ë³„ì¹­ì´ ì¶”ê°€ë¨\n"
addoptions.comment = "제목 설명"
addoptions.file = "PEM íŒŒì¼ ì´ë¦„"
-addoptions.global = "ì¸ì¦ì„œë¥¼ 글로벌 매핑 파ì¼ì— 추가"
+addoptions.global = "글로벌 매핑 파ì¼ì— ì¸ì¦ì„œ 추가"
-addoptions.subject = "SAML 제목"
+addoptions.subject = "SAML 주체"
-addoptions.username = "추가ë˜ëŠ” ì¸ì¦ì„œ 저장소를 소유한 사용ìž"
+addoptions.username = "ì¸ì¦ì„œ 저장소를 추가 ì¤‘ì¸ ì‚¬ìš©ìž"
-addoptions.verbose = "세부 작업"
+addoptions.verbose = "ìžì„¸í•œ ì •ë³´ 표시 ìž‘ì—…"
-cmdline.parse = "ëª…ë ¹ì¤„ì„ êµ¬ë¬¸ 분ì„하지 못함"
+cmdline.parse = "명령줄 구문 ë¶„ì„ ì‹¤íŒ¨"
cmdline.summary.pemfile = "PEM 파ì¼"
cmdline.summary.subject = "제목"
-cmdline.summary.username = "username"
-cmdline.summary.comm = "ì˜ê²¬"
+cmdline.summary.username = "ì‚¬ìš©ìž ì´ë¦„"
+cmdline.summary.comm = "설명"
list.comment = "설명"
-list.count = "%1$s '%3$s' 사용ìžì— 대한 ë³„ì¹­ì„ %2$dê°œ 찾았습니다.\n"
+list.count = "%1$sì—ì„œ ì‚¬ìš©ìž '%3$s'ì˜ %2$dê°œ ë³„ì¹­ì´ í™•ì¸ë˜ì—ˆìŠµë‹ˆë‹¤.\n"
-list.error = "%1$s: '%2$s' 사용ìžì— 대한 ë³„ì¹­ì„ ë‚˜ì—´í•˜ì§€ 못했습니다. %3$s.\n"
+list.error = "%1$s: ì‚¬ìš©ìž '%2$s'ì˜ ë³„ì¹­ì„ ë‚˜ì—´í•˜ì§€ 못했습니다. %3$s.\n"
list.subject = "제목"
-listmapped.count = "%1$s ë§¤í•‘ëœ ë³„ì¹­ì„ %2$dê°œ 찾았습니다.\n"
+listmapped.count = "%1$sì—ì„œ %2$dê°œì˜ ë§¤í•‘ëœ ë³„ì¹­ì„ ì°¾ì•˜ìŠµë‹ˆë‹¤.\n"
-listmapped.error = "%1$s: %2$sì— ëŒ€í•œ ë§¤í•‘ëœ ë³„ì¹­ì„ ë‚˜ì—´í•˜ì§€ 못했습니다.\n"
+listmapped.error = "%1$s: ë§¤í•‘ëœ ë³„ì¹­ì„ ë‚˜ì—´í•˜ì§€ 못했습니다. %2$s.\n"
listmapped.subject = "제목"
listmapped.username = "ì‚¬ìš©ìž ì´ë¦„"
-listoptions.username =
- "쿼리ë˜ëŠ” ì¸ì¦ì„œ 저장소를 소유한 사용ìž"
+listoptions.username = "ì¸ì¦ì„œ 저장소를 쿼리 ì¤‘ì¸ ì‚¬ìš©ìž"
-listoptions.verbose = "세부 작업"
+listoptions.verbose = "ìžì„¸í•œ ì •ë³´ 표시 ìž‘ì—…"
loadfile.fail = "%1$s: PEM íŒŒì¼ '%2$s'ì„(를) ì½ì„ 수 없습니다.\n"
-name.any = "<ìž„ì˜>"
+name.any = "<모ë‘>"
-removesubj.fail = "%1$s: '%2$s' 사용ìžì— 대한 ë³„ì¹­ì„ ì œê±°í•˜ì§€ 못했습니다. %3$s.\n"
+removesubj.fail = "%1$s: ì‚¬ìš©ìž '%2$s'ì— ëŒ€í•œ ë³„ì¹­ì„ ì œê±°í•˜ì§€ 못했습니다. %3$s.\n"
-removesubj.success = "%1$s: ë³„ì¹­ì´ ì œê±°ë˜ì—ˆìŠµë‹ˆë‹¤.\n"
+removesubj.success = "%1$s: ë³„ì¹­ì´ ì œê±°ë¨\n"
removeoptions.file = "PEM íŒŒì¼ ì´ë¦„"
-removeoptions.subject = "SAML 제목"
-removeoptions.username =
- "제거ë˜ëŠ” ì¸ì¦ì„œ 저장소를 소유한 사용ìž"
+removeoptions.subject = "SAML 주체"
+removeoptions.username = "ì¸ì¦ì„œ 저장소를 제거 ì¤‘ì¸ ì‚¬ìš©ìž"
-removeoptions.verbose = "세부 작업"
+removeoptions.verbose = "ìžì„¸í•œ ì •ë³´ 표시 ìž‘ì—…"
-vgauth.init.failed = "VGAuth를 초기화하지 못했습니다."
+vgauth.init.failed = "VGAuth 초기화 실패"
diff --git a/open-vm-tools/vgauth/cli/l10n/zh_CN.vmsg b/open-vm-tools/vgauth/cli/l10n/zh_CN.vmsg
index 93f963f2..bf161d3d 100644
--- a/open-vm-tools/vgauth/cli/l10n/zh_CN.vmsg
+++ b/open-vm-tools/vgauth/cli/l10n/zh_CN.vmsg
@@ -16,62 +16,60 @@
#
##########################################################
-addsubj.fail = "%1$s: 未能为用户“%2$sâ€æ·»åŠ åˆ«å: %3$s。\n"
-addsubj.success = "%1$s: 别å已添加\n"
+addsubj.fail = "%1$s: 无法为用户“%2$sâ€æ·»åŠ åˆ«å: %3$s。\n"
+addsubj.success = "%1$s: 已添加别å\n"
-addoptions.comment = "主题备注"
+addoptions.comment = "主题注释"
addoptions.file = "PEM 文件å"
-addoptions.global = "å°†è¯ä¹¦æ·»åŠ åˆ°å…¨å±€æ˜ å°„文件"
+addoptions.global = "å°†è¯ä¹¦æ·»åŠ åˆ°å…¨å±€æ˜ å°„文件中"
addoptions.subject = "SAML 主题"
-addoptions.username = "è¦å‘å…¶è¯ä¹¦å­˜å‚¨æ·»åŠ è¯ä¹¦çš„用户"
+addoptions.username = "è¦åœ¨ä»¥ä¸‹ä½ç½®æ·»åŠ è¯ä¹¦å­˜å‚¨çš„用户"
-addoptions.verbose = "Verbose æ“作"
+addoptions.verbose = "详细æ“作"
-cmdline.parse = "命令行解æžå¤±è´¥"
+cmdline.parse = "命令行分æžå¤±è´¥"
cmdline.summary.pemfile = "PEM 文件"
cmdline.summary.subject = "主题"
-cmdline.summary.username = "username"
-cmdline.summary.comm = "备注"
+cmdline.summary.username = "用户å"
+cmdline.summary.comm = "注释"
-list.comment = "备注"
-list.count = "%1$s 找到用户“%3$sâ€çš„ %2$d 个别å\n"
+list.comment = "注释"
+list.count = "%1$s 已找到用户“%3$sâ€çš„ %2$d 别å\n"
-list.error = "%1$s: 未能列出用户“%2$sâ€çš„别å: %3$s。\n"
+list.error = "%1$s: 无法列出用户“%2$sâ€çš„别å: %3$s。\n"
list.subject = "主题"
-listmapped.count = "%1$s 找到 %2$d 个映射的别å\n"
+listmapped.count = "%1$s 已找到 %2$d 映射的别å\n"
-listmapped.error = "%1$s: 未能列出映射的别å: %2$s。\n"
+listmapped.error = "%1$s: 无法列出映射的别å: %2$s。\n"
listmapped.subject = "主题"
listmapped.username = "用户å"
-listoptions.username =
- "è¦å¯¹å…¶è¯ä¹¦å­˜å‚¨è¿›è¡ŒæŸ¥è¯¢çš„用户"
+listoptions.username = "è¦æŸ¥è¯¢å…¶è¯ä¹¦å­˜å‚¨çš„用户"
-listoptions.verbose = "Verbose æ“作"
+listoptions.verbose = "详细æ“作"
loadfile.fail = "%1$s: æ— æ³•è¯»å– PEM 文件“%2$sâ€\n"
-name.any = "<ä»»æ„>"
+name.any = "<任何>"
-removesubj.fail = "%1$s: 未能移除用户“%2$sâ€çš„别å: %3$s。\n"
+removesubj.fail = "%1$s: 无法删除用户“%2$sâ€çš„别å: %3$s。\n"
-removesubj.success = "%1$s: 别å已移除\n"
+removesubj.success = "%1$s: 已删除别å\n"
removeoptions.file = "PEM 文件å"
removeoptions.subject = "SAML 主题"
-removeoptions.username =
- "è¦ä»Žå…¶è¯ä¹¦å­˜å‚¨ä¸­ç§»é™¤è¯ä¹¦çš„用户"
+removeoptions.username = "è¦ä»Žä»¥ä¸‹ä½ç½®åˆ é™¤è¯ä¹¦å­˜å‚¨çš„用户"
-removeoptions.verbose = "Verbose æ“作"
+removeoptions.verbose = "详细æ“作"
-vgauth.init.failed = "未能åˆå§‹åŒ– VGAuth"
+vgauth.init.failed = "无法åˆå§‹åŒ– VGAuth"
diff --git a/open-vm-tools/vgauth/cli/l10n/zh_TW.vmsg b/open-vm-tools/vgauth/cli/l10n/zh_TW.vmsg
index 20cad7f3..5e48d625 100644
--- a/open-vm-tools/vgauth/cli/l10n/zh_TW.vmsg
+++ b/open-vm-tools/vgauth/cli/l10n/zh_TW.vmsg
@@ -53,8 +53,7 @@ listmapped.subject = "主旨"
listmapped.username = "使用者å稱"
-listoptions.username =
- "æ­£è¦æŸ¥è©¢å…¶æ†‘證存放å€çš„使用者"
+listoptions.username = "æ­£è¦æŸ¥è©¢å…¶æ†‘證存放å€çš„使用者"
listoptions.verbose = "詳細資訊作業"
@@ -69,8 +68,7 @@ removesubj.success = "%1$s: 已移除別å\n"
removeoptions.file = "PEM 檔案å稱"
removeoptions.subject = "SAML 主旨"
-removeoptions.username =
- "正從以下項目中移除其憑證存放å€çš„使用者"
+removeoptions.username = "正從以下項目中移除其憑證存放å€çš„使用者"
removeoptions.verbose = "詳細資訊作業"
diff --git a/open-vm-tools/vgauth/cli/main.c b/open-vm-tools/vgauth/cli/main.c
index 7755e1c6..1efa658a 100644
--- a/open-vm-tools/vgauth/cli/main.c
+++ b/open-vm-tools/vgauth/cli/main.c
@@ -41,7 +41,7 @@
#include "i18n.h"
#include "prefs.h"
-static const gchar *appName;
+static gchar *appName;
static gboolean verbose = FALSE;
@@ -458,7 +458,7 @@ mainRun(int argc,
};
GOptionContext *context;
- appName = g_basename(argv[0]);
+ appName = g_path_get_basename(argv[0]);
/*
* The option parser needs to modify these, and using the variables
@@ -586,6 +586,7 @@ mainRun(int argc,
}
VGAuth_Shutdown(ctx);
+ g_free(appName);
return (err == VGAUTH_E_OK) ? 0 : -1;
}
diff --git a/open-vm-tools/vgauth/common/certverify.c b/open-vm-tools/vgauth/common/certverify.c
index 3fa6cae0..b4507de2 100644
--- a/open-vm-tools/vgauth/common/certverify.c
+++ b/open-vm-tools/vgauth/common/certverify.c
@@ -379,6 +379,75 @@ done:
/*
******************************************************************************
+ * CertVerifyX509ToString -- */ /**
+ *
+ * Debug support for X509 certs; convert them to human readable text.
+ *
+ * @param[in] x An X509 structure containing a cert.
+ *
+ * @return Allocated string containing the cert in human-readable text.
+ *
+ ******************************************************************************
+ */
+
+static gchar *
+CertVerifyX509ToString(X509 *x)
+{
+ BIO *mem;
+ char *str;
+ gchar *retVal;
+ int len;
+
+ mem = BIO_new(BIO_s_mem());
+ if (!mem) {
+ g_warning("%s: out of memory creating BIO\n", __FUNCTION__);
+ return NULL;
+ }
+
+ X509_print(mem, x);
+
+ len = BIO_get_mem_data(mem, &str);
+
+ retVal = g_strndup(str, len);
+
+ BIO_set_close(mem, BIO_CLOSE);
+ BIO_free(mem);
+
+ return retVal;
+}
+
+
+/*
+ ******************************************************************************
+ * CertVerify_CertToX509String -- */ /**
+ *
+ * Debug support for certs; convert them to human readable text.
+ *
+ * @param[in] pemCert A certficate in PEM format.
+ *
+ * @return Allocated string containing the cert in human-readable text.
+ *
+ ******************************************************************************
+ */
+
+gchar *
+CertVerify_CertToX509String(const gchar *pemCert)
+{
+ X509 *x = NULL;
+ gchar *retVal = NULL;
+
+ x = CertStringToX509(pemCert);
+ if (x) {
+ retVal = CertVerifyX509ToString(x);
+ }
+ X509_free(x);
+
+ return retVal;
+}
+
+
+/*
+ ******************************************************************************
* CertVerify_IsWellFormedPEMCert -- */ /**
*
* Checks to see if a PEM cert string can be converted into a x509
diff --git a/open-vm-tools/vgauth/common/certverify.h b/open-vm-tools/vgauth/common/certverify.h
index 5b9f9f6e..3931d857 100644
--- a/open-vm-tools/vgauth/common/certverify.h
+++ b/open-vm-tools/vgauth/common/certverify.h
@@ -56,4 +56,6 @@ VGAuthError CertVerify_CheckSignatureUsingCert(VGAuthHashAlg hash,
gchar * CertVerify_StripPEMCert(const gchar *pemCert);
+gchar * CertVerify_CertToX509String(const gchar *pemCert);
+
#endif // _CERTVERIFY_H_
diff --git a/open-vm-tools/vgauth/lib/authPosix.c b/open-vm-tools/vgauth/lib/authPosix.c
index 7ff3b882..52f98e17 100644
--- a/open-vm-tools/vgauth/lib/authPosix.c
+++ b/open-vm-tools/vgauth/lib/authPosix.c
@@ -32,12 +32,18 @@
* USE_PAM should be defined in the makefile, since it impacts
* what system libraries (-ld, -lcrypt) will be needed.
*
- * XXX The non-PAM case builds, but is currently untested (since it can't work
- * with Linux security).
+ * XXX non-PAM code doesn't enforce a delay after failure to
+ * slow down a brute-force attack.
*/
#ifdef USE_PAM
# include <security/pam_appl.h>
# include <dlfcn.h>
+#else
+# ifdef __APPLE__
+# error - Apple not supported.
+# else
+# include <shadow.h>
+# endif
#endif
#include <pwd.h>
@@ -323,15 +329,25 @@ VGAuthValidateUsernamePasswordImpl(VGAuthContext *ctx,
}
if (*pwd->pw_passwd != '\0') {
- char *namep = (char *) crypt(password, pwd->pw_passwd);
+ const char *passwd = pwd->pw_passwd;
+ const char *crypt_pw;
+
+ // looks like a shadow password, so use it instead
+ if (strcmp(passwd, "x") == 0) {
+ struct spwd *sp = getspnam(userName);
+ if (sp) {
+ passwd = sp->sp_pwdp;
+ }
+ }
- if (strcmp(namep, pwd->pw_passwd)) {
+ crypt_pw = crypt(password, passwd);
+ if (!crypt_pw || (strcmp(crypt_pw, passwd) != 0)) {
// Incorrect password
return VGAUTH_E_AUTHENTICATION_DENIED;
}
// Clear out crypt()'s internal state, too.
- crypt("glurp", pwd->pw_passwd);
+ crypt("glurp", passwd);
}
#endif /* !USE_PAM */
diff --git a/open-vm-tools/vgauth/lib/common.c b/open-vm-tools/vgauth/lib/common.c
index 7bd31925..15ef92e3 100644
--- a/open-vm-tools/vgauth/lib/common.c
+++ b/open-vm-tools/vgauth/lib/common.c
@@ -322,9 +322,9 @@ VGAuth_InstallClient(VGAuthContext *ctx,
"# \n"
"# This file was generated by vgauth\n"
"# \n"
-"auth sufficient pam_unix2.so shadow nullok\n"
-"auth sufficient pam_unix.so shadow nullok\n"
-"auth required pam_unix_auth.so shadow nullok\n"
+"auth sufficient pam_unix2.so shadow\n"
+"auth sufficient pam_unix.so shadow\n"
+"auth required pam_unix_auth.so shadow\n"
"account sufficient pam_unix2.so\n"
"account sufficient pam_unix.so\n"
"account required pam_unix_auth.so\n";
diff --git a/open-vm-tools/vgauth/lib/l10n/de.vmsg b/open-vm-tools/vgauth/lib/l10n/de.vmsg
index a38547d0..c712d31e 100644
--- a/open-vm-tools/vgauth/lib/l10n/de.vmsg
+++ b/open-vm-tools/vgauth/lib/l10n/de.vmsg
@@ -16,6 +16,6 @@
#
##########################################################
-auth.password.invalid = "Keine Übereinstimmung bei Benutzername und Kennwort für '%1$s'"
-auth.password.valid = "Benutzername und Kennwort erfolgreich validiert für '%1$s'"
-auth.sspi.badid = "Versuch der Authentifizierung mit einer ungültigen oder abgelaufenen SSPI-Challenge-ID: %1$u"
+auth.password.invalid = "Benutzername und Kennwort für '%1$s' stimmen nicht überein"
+auth.password.valid = "Benutzername und Kennwort wurden erfolgreich für '%1$s' bestätigt"
+auth.sspi.badid = "Versuch der Authentifizierung mithilfe einer ungültigen oder abgelaufenen SSPI-Anfrage-ID: %1$u"
diff --git a/open-vm-tools/vgauth/lib/l10n/fr.vmsg b/open-vm-tools/vgauth/lib/l10n/fr.vmsg
index 1952a8ef..a2364a19 100644
--- a/open-vm-tools/vgauth/lib/l10n/fr.vmsg
+++ b/open-vm-tools/vgauth/lib/l10n/fr.vmsg
@@ -16,6 +16,6 @@
#
##########################################################
-auth.password.invalid = "Le nom d'utilisateur et le mot de passe ne correspondent pas pour '%1$s'"
-auth.password.valid = "Nom d'utilisateur et mot de passe validés avec succès pour '%1$s'"
-auth.sspi.badid = "Tentative d'authentification en utilisant un ID de demande SSPI non valide ou expiré : %1$u"
+auth.password.invalid = "Non-concordance du nom d'utilisateur et du mot de passe pour '%1$s'"
+auth.password.valid = "Validation réussie du nom d'utilisateur et du mot de passe pour '%1$s'"
+auth.sspi.badid = "Tentative d'authentification à l'aide d'un ID de demande SSPI non valide ou expiré : %1$u"
diff --git a/open-vm-tools/vgauth/lib/l10n/it.vmsg b/open-vm-tools/vgauth/lib/l10n/it.vmsg
index 7fb6ce34..0cdc1b45 100644
--- a/open-vm-tools/vgauth/lib/l10n/it.vmsg
+++ b/open-vm-tools/vgauth/lib/l10n/it.vmsg
@@ -16,6 +16,6 @@
#
##########################################################
-auth.password.invalid = "Nome utente e password non corrispondenti per "%1$s""
-auth.password.valid = "Nome utente e password convalidati correttamente per "%1$s""
+auth.password.invalid = "Nome utente e password non corrispondenti per '%1$s'"
+auth.password.valid = "Nome utente e password convalidati correttamente per '%1$s'"
auth.sspi.badid = "Tentativo di autenticazione utilizzando un ID test SSPI non valido o scaduto: %1$u"
diff --git a/open-vm-tools/vgauth/lib/l10n/ja.vmsg b/open-vm-tools/vgauth/lib/l10n/ja.vmsg
index 0da47023..a5c74ea3 100644
--- a/open-vm-tools/vgauth/lib/l10n/ja.vmsg
+++ b/open-vm-tools/vgauth/lib/l10n/ja.vmsg
@@ -16,6 +16,6 @@
#
##########################################################
-auth.password.invalid = "「%1$sã€ã«å¯¾ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードãŒä¸€è‡´ã—ã¾ã›ã‚“"
-auth.password.valid = "「%1$sã€ã«å¯¾ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードãŒæ­£å¸¸ã«æ¤œè¨¼ã•ã‚Œã¾ã—ãŸ"
-auth.sspi.badid = "無効ã¾ãŸã¯æœŸé™åˆ‡ã‚Œã® SSPI ãƒãƒ£ãƒ¬ãƒ³ã‚¸ ID を使用ã—ã¦èªè¨¼ã—よã†ã¨ã—ã¦ã„ã¾ã™: %1$u"
+auth.password.invalid = "'%1$s' ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードãŒä¸€è‡´ã—ã¾ã›ã‚“"
+auth.password.valid = "'%1$s' ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードãŒæ­£ã—ã検証ã•ã‚Œã¾ã—ãŸ"
+auth.sspi.badid = "無効ã¾ãŸã¯æœŸé™åˆ‡ã‚Œã® SSPI ãƒãƒ£ãƒ¬ãƒ³ã‚¸ ID を使用ã—ã¦èªè¨¼ã‚’試ã¿ã¾ã™: %1$u"
diff --git a/open-vm-tools/vgauth/lib/l10n/ko.vmsg b/open-vm-tools/vgauth/lib/l10n/ko.vmsg
index 6297c97e..f1d1c294 100644
--- a/open-vm-tools/vgauth/lib/l10n/ko.vmsg
+++ b/open-vm-tools/vgauth/lib/l10n/ko.vmsg
@@ -16,6 +16,6 @@
#
##########################################################
-auth.password.invalid = "'%1$s'ì— ëŒ€í•œ ì‚¬ìš©ìž ì´ë¦„ê³¼ 암호가 ì¼ì¹˜í•˜ì§€ 않습니다."
-auth.password.valid = "'%1$s'ì— ëŒ€í•œ ì‚¬ìš©ìž ì´ë¦„ê³¼ ì•”í˜¸ì˜ ìœ íš¨ì„±ì„ í™•ì¸í–ˆìŠµë‹ˆë‹¤."
-auth.sspi.badid = "잘못ë˜ê±°ë‚˜ ë§Œë£Œëœ SSPI 요청 ID(%1$u)를 사용하여 ì¸ì¦í•˜ë ¤ê³  했습니다."
+auth.password.invalid = "'%1$s'ì— ëŒ€í•´ ì‚¬ìš©ìž ì´ë¦„ê³¼ 암호가 ì¼ì¹˜í•˜ì§€ 않습니다."
+auth.password.valid = "'%1$s'ì— ëŒ€í•´ ì‚¬ìš©ìž ì´ë¦„ ë° ì•”í˜¸ê°€ 유효한 것으로 확ì¸ë˜ì—ˆìŠµë‹ˆë‹¤."
+auth.sspi.badid = "잘못ë˜ì—ˆê±°ë‚˜ ë§Œë£Œëœ SSPI 챌린지 ID를 사용하여 ì¸ì¦í•˜ë ¤ê³  합니다. %1$u"
diff --git a/open-vm-tools/vgauth/service/l10n/de.vmsg b/open-vm-tools/vgauth/service/l10n/de.vmsg
index 7fb51ff1..3f23d32b 100644
--- a/open-vm-tools/vgauth/service/l10n/de.vmsg
+++ b/open-vm-tools/vgauth/service/l10n/de.vmsg
@@ -16,31 +16,31 @@
#
##########################################################
-proto.attack = "Möglicher Angriff auf die Sicherheit! Anforderungstyp %1$d hat einen userName (%2$s), der nicht dem Pipe-Eigentümer (%3$s) entspricht!"
+proto.attack = "Möglicher Sicherheitsangriff! Der Anfragetyp %1$d verfügt über einen Benutzernamen (%2$s), der nicht mit dem Pipe-Eigentümer (%3$s) übereinstimmt!"
-validate.samlBearer.fail = "Fehler bei Validierung des SAML-Bearer-Tokens: %1$d"
+validate.samlBearer.fail = "Die Überprüfung des SAML-Träger-Token ist fehlgeschlagen: %1$d"
-validate.samlBearer.success = "Validiertes SAML-Bearer-Token für Benutzer '%1$s'"
+validate.samlBearer.success = "Überprüfter SAML-Träger-Token für den Benutzer '%1$s'"
-alias.addid = "Alias hinzugefügt zu Aliasspeicher von '%1$s' durch Benutzer '%2$s'"
+alias.addid = "Dem Aliasspeicher im Eigentum von '%1$s' durch den Benutzer '%2$s' hinzugefügtes Alias"
-alias.dir.badperm = "Aliasspeicherverzeichnis '%1$s' weist einen falschen Eigentümer oder falsche Berechtigungen auf. Alle derzeit in '%2$s' gespeicherten Aliase stehen nicht zur Authentifizierung zur Verfügung."
+alias.dir.badperm = "Das Aliasspeicherverzeichnis '%1$s' verfügt über unzulässige Eigentümer oder Berechtigungen. Alle aktuell in '%2$s' gespeicherte Aliase stehen für die Authentifizierung nicht zur Verfügung"
-alias.dir.notadir = "Aliasspeicherverzeichnis '%1$s' ist vorhanden, aber kein Verzeichnis."
+alias.dir.notadir = "Das Aliasspeicherverzeichnis '%1$s' ist vorhanden, ist aber kein Verzeichnis"
-alias.dir.renamefail = "Fehler beim Umbenennen des zweifelhaften Aliasspeicherverzeichnisses '%1$s' in '%2$s'"
+alias.dir.renamefail = "Das Umbenennen des verdächtigen Aliasspeicherverzeichnisses '%1$s' in '%2$s' ist fehlgeschlagen"
-alias.alias.badfile = "Der Aliasspeicher '%1$s' ist vorhanden, ist aber keine reguläre Datei. Die Aliase für Benutzer '%2$s' stehen nicht zur Authentifizierung zur Verfügung."
+alias.alias.badfile = "Der Aliasspeicher '%1$s' ist vorhanden, ist aber keine ordnungsgemäße Datei. Die Aliase für den Benutzer '%2$s' stehen für die Authentifizierung nicht zur Verfügung"
-alias.alias.badperm = "Der Aliasspeicher '%1$s' weist einen falschen Eigentümer oder falsche Berechtigungen auf. Die Aliase für Benutzer '%2$s' stehen nicht zur Authentifizierung zur Verfügung."
+alias.alias.badperm = "Der Aliasspeicher '%1$s' verfügt über unzulässige Eigentümer oder Berechtigungen. Die Aliase für den Benutzer '%2$s' stehen für die Authentifizierung nicht zur Verfügung"
-alias.alias.rename = "Zweifelhafter Aliasspeicher '%1$s' umbenannt in '%2$s'"
+alias.alias.rename = "Der verdächtige Aliasspeicher '%1$s' wurde in '%2$s' umbenannt"
-alias.alias.renamefail = "Fehler beim Umbenennen des zweifelhaften Aliasspeichers '%1$s' in '%2$s'"
+alias.alias.renamefail = "Das Umbenennen des verdächtigen Aliasspeichers '%1$s' in '%2$s' ist fehlgeschlagen"
-alias.mapfile.badperm = "Die Zuordnungsdatei des Aliasspeichers '%1$s' weist einen falschen Eigentümer oder falsche Berechtigungen auf. Die Aliase in der Zuordnungsdatei stehen nicht zur Authentifizierung zur Verfügung."
+alias.mapfile.badperm = "Die Zuordungsdatei '%1$s' des Aliasspeichers verfügt über unzulässige Eigentümer oder Berechtigungen. Die Aliase in der Zuordnungsdatei stehen für eine Authentifizierung nicht zur Verfügung"
-alias.mapping.badfile = "Die Zuordnungsdatei '%1$s' ist vorhanden, aber keine reguläre Datei. Die Aliase in der Zuordnungsdatei stehen nicht zur Authentifizierung zur Verfügung."
+alias.mapping.badfile = "Die Zuordnungsdatei '%1$s' ist vorhanden, ist aber keine ordnungsgemäße Datei. Die Aliase in der Zuordnungsdatei stehen für eine Authentifizierung nicht zur Verfügung"
-alias.removeid = "Alias gelöscht aus Aliasspeicher von '%1$s' durch Benutzer '%2$s'"
+alias.removeid = "Das Alias wurde aus dem Aliasspeicher im Eigentum von '%1$s' durch den Benutzer '%2$s' entfernt"
diff --git a/open-vm-tools/vgauth/service/l10n/es.vmsg b/open-vm-tools/vgauth/service/l10n/es.vmsg
index 675ada42..670ae61e 100644
--- a/open-vm-tools/vgauth/service/l10n/es.vmsg
+++ b/open-vm-tools/vgauth/service/l10n/es.vmsg
@@ -16,57 +16,31 @@
#
##########################################################
-proto.attack = "!Posible ataque de seguridad" El tipo de solicitud %1$d tiene un "
- "userName (%2$s) que no coincide con el propietario de del canal (%3$s)!"
+proto.attack = "Posible ataque de seguridad. El tipo de solicitud %1$d tiene un nombre de usuario (%2$s) que no coincide con el propietario de la canalización (%3$s)."
-validate.samlBearer.fail =
- "Error de validación de token de portador SAML: %1$d"
+validate.samlBearer.fail = "Error de validación de token de portador SAML: %1$d"
-validate.samlBearer.success =
- "Token de portador SAML validado para el usuario '%1$s'"
+validate.samlBearer.success = "Token de portador SAML validado para el usuario '%1$s'"
-alias.addid =
- "El usuario '%2$s' ha añadido el alias al almacén de alias propiedad de '%1$s'"
+alias.addid = "El usuario '%2$s' ha agregado el alias al almacén de alias propiedad de '%1$s'"
-alias.dir.badperm =
- "El directorio de almacén de alias '%1$s' tiene un propietario o "
- "permisos incorrectos. "
- "Cualquier alias actualmente almacenado en '%2$s' no estará "
- "disponibles para autenticación"
+alias.dir.badperm = "El directorio de almacenamiento de alias '%1$s' tiene un propietario o permisos incorrectos. Los alias almacenados actualmente en '%2$s' no estarán disponibles para la autenticación"
-alias.dir.notadir = "El directorio de almacén de alias '%1$s' existe pero no es un directorio"
+alias.dir.notadir = "El directorio de almacenamiento de alias '%1$s' existe, pero no es un directorio"
-alias.dir.renamefail =
- "No ha podido cambiarse el nombre del supuesto directorio de almacén de alias de '%1$s' a '%2$s'"
+alias.dir.renamefail = "No se pudo cambiar el nombre del directorio de almacenamiento de alias sospechoso de '%1$s' a '%2$s'"
-alias.alias.badfile =
- "El almacén de alias '%1$s' existe pero no es un archivo normal. "
- "El alias del usuario '%2$s' no estará disponible para "
- "autenticación"
+alias.alias.badfile = "El almacén de alias '%1$s' existe, pero no es un archivo normal. Los alias del usuario '%2$s' no estarán disponibles para la autenticación"
-alias.alias.badperm =
- "El Alias del almacén '%1$s'tiene un propietario"
- " o permisos incorrectos. "
- "Los alias del usuario '%2$s' no estarán disponibles "
- "para autenticación"
+alias.alias.badperm = "El almacén de alias '%1$s' tiene un propietario o permisos incorrectos. Los alias del usuario '%2$s' no estarán disponibles para la autenticación"
+alias.alias.rename = "El nombre del almacén de alias sospechoso '%1$s' ha cambiado a '%2$s'"
-alias.alias.rename = "El nombre del supuesto almacén de alias '%1$s' ha cambiado a '%2$s'"
+alias.alias.renamefail = "No pudo cambiarse el nombre del almacén de alias sospechoso de '%1$s' a '%2$s'"
-alias.alias.renamefail =
- "No ha podido cambiarse el nombre del supuesto almacén de alias de '%1$s' a '%2$s'"
+alias.mapfile.badperm = "El archivo de asignación del almacén de alias '%1$s' tiene un propietario o permisos incorrectos. Los alias del archivo de asignación no estarán disponibles para la autenticación"
-alias.mapfile.badperm =
- "El archivo de asignación del almacén de alias '%1$s' tiene un"
- " propietario o permisos incorrectos. "
- "Los alias del archivo de asignación no estarán "
- "disponibles para autenticación"
+alias.mapping.badfile = "El archivo de asignación '%1$s' existe, pero no es un archivo normal. Los alias del archivo de asignación no estarán disponibles para la autenticación"
-alias.mapping.badfile =
- "El archivo de asignación '%1$s' existe pero no es un archivo normal. "
- "Los alias del archivo de asignación no estarán "
- "disponibles para autenticación"
-
-alias.removeid =
- "El usuario '%2$s' ha eliminado el Alias del almacén de alias propiedad de '%1$s'"
+alias.removeid = "El usuario '%2$s' ha quitado el alias del almacén de alias propiedad de '%1$s'"
diff --git a/open-vm-tools/vgauth/service/l10n/fr.vmsg b/open-vm-tools/vgauth/service/l10n/fr.vmsg
index 1f15a714..a936c04b 100644
--- a/open-vm-tools/vgauth/service/l10n/fr.vmsg
+++ b/open-vm-tools/vgauth/service/l10n/fr.vmsg
@@ -16,31 +16,31 @@
#
##########################################################
-proto.attack = "Attaque de sécurité potentielle ! Le type de requête %1$d a un userName (%2$s) qui ne correspond pas au propriétaire du canal (%3$s) !"
+proto.attack = "Attaque possible au niveau de la sécurité ! Le type de demande %1$d a un nom d'utilisateur (%2$s) ne correspondant pas au propriétaire du canal (%3$s) !"
-validate.samlBearer.fail = "Échec de la validation du jeton de support SAML : %1$d"
+validate.samlBearer.fail = "Échec de la validation du jeton de support SAML : %1$d"
validate.samlBearer.success = "Jeton de support SAML validé pour l'utilisateur '%1$s'"
-alias.addid = "Alias ajouté au magasin d'alias appartenant à '%1$s' par l'utilisateur '%2$s'"
+alias.addid = "Alias ajouté au magasin d'alias détenu par '%1$s' par l'utilisateur '%2$s'"
-alias.dir.badperm = "Le répertoire du magasin d'alias '%1$s' a un propriétaire ou des autorisations incorrects. Les alias actuellement stockés dans '%2$s' ne seront pas disponibles pour l'authentification"
+alias.dir.badperm = "Le répertoire du magasin d'alias '%1$s' a un détenteur ou des autorisations incorrects. Tous les alias actuellement stockés dans '%2$s' ne seront pas disponibles pour l'authentification"
-alias.dir.notadir = "Le répertoire du magasin d'alias '%1$s' existe mais n'est pas un répertoire"
+alias.dir.notadir = "Le répertoire du magasin d'alias '%1$s' existe mais il ne s'agit pas d'un répertoire"
-alias.dir.renamefail = "Impossible de renommer le répertoire du magasin d'alias suspect '%1$s' en '%2$s'"
+alias.dir.renamefail = "Échec de la modification du nom du répertoire du magasin d'alias suspect '%1$s' en '%2$s'"
-alias.alias.badfile = "Le magasin d'alias '%1$s' existe, mais n'est pas un fichier standard. Les alias de l'utilisateur '%2$s' ne seront pas disponibles pour l'authentification"
+alias.alias.badfile = "Le magasin d'alias '%1$s' existe mais il ne s'agit pas d'un fichier normal. Les alias de l'utilisateur '%2$s' ne seront pas disponibles pour l'authentification"
-alias.alias.badperm = "Le magasin d'alias '%1$s' a un propriétaire ou des autorisations incorrects. Les alias de l'utilisateur '%2$s' ne seront pas disponibles pour l'authentification"
+alias.alias.badperm = "Le magasin d'alias '%1$s' a un détenteur ou des autorisations incorrects. Les alias de l'utilisateur '%2$s' ne seront pas disponibles pour l'authentification"
alias.alias.rename = "Magasin d'alias suspect '%1$s' renommé en '%2$s'"
-alias.alias.renamefail = "Impossible de renommer le magasin d'alias suspect '%1$s' en '%2$s'"
+alias.alias.renamefail = "Échec de la modification du nom du magasin d'alias suspect '%1$s' en '%2$s'"
-alias.mapfile.badperm = "Le fichier de mappage du magasin d'alias '%1$s' a un propriétaire ou des autorisations incorrects. Les alias dans le fichier de mappage ne seront pas disponibles pour l'authentification"
+alias.mapfile.badperm = "Le fichier de mappage du magasin d'alias '%1$s' a un détenteur ou des autorisations incorrects. Les alias dans le fichier de mappage ne seront pas disponibles pour l'authentification"
-alias.mapping.badfile = "Le fichier de mappage '%1$s' existe, mais n'est pas un fichier standard. Les alias dans le fichier de mappage ne seront pas disponibles pour l'authentification"
+alias.mapping.badfile = "Le fichier de mappage '%1$s' existe mais il ne s'agit pas d'un fichier normal. Les alias dans le fichier de mappage ne seront pas disponibles pour l'authentification"
-alias.removeid = "Alias supprimé du magasin d'alias appartenant à '%1$s' par l'utilisateur '%2$s'"
+alias.removeid = "Alias supprimés du magasin d'alias détenu par '%1$s' par l'utilisateur '%2$s'"
diff --git a/open-vm-tools/vgauth/service/l10n/it.vmsg b/open-vm-tools/vgauth/service/l10n/it.vmsg
index e0728183..bb9e152d 100644
--- a/open-vm-tools/vgauth/service/l10n/it.vmsg
+++ b/open-vm-tools/vgauth/service/l10n/it.vmsg
@@ -16,57 +16,31 @@
#
##########################################################
-proto.attack = "Possibile attacco alla sicurezza. Il tipo di richiesta %1$d ha un "
- "nome utente (%2$s) non corrispondente al proprietario pipe (%3$s)!"
+proto.attack = "Possibile attacco alla sicurezza. Il tipo di richiesta %1$d ha un nome utente (%2$s) che non corrisponde al proprietario del circuito (%3$s)!"
-validate.samlBearer.fail =
- "Convalida del token di connessione SAML non riuscita: %1$d"
+validate.samlBearer.fail = "Convalida del token di connessione SAML non riuscita: %1$d"
-validate.samlBearer.success =
- "Token di connessione SAML convalidato per l'utente "%1$s""
+validate.samlBearer.success = "Token di connessione SAML convalidato per l'utente '%1$s'"
-alias.addid =
- "Alias aggiunto all'archivio Alias di proprietà di "%1$s" dall'utente "%2$s""
+alias.addid = "Alias aggiunto all'archivio Alias di proprietà di '%1$s' dall'utente '%2$s'"
-alias.dir.badperm =
- "La directory dell'archivio di alias "%1$s" ha un proprietario o autorizzazioni "
- "errate. "
- "Tutti gli alias attualmente archiviati in "%2$s" non saranno "
- "disponibili per l'autenticazione"
+alias.dir.badperm = "La directory di archiviazione alias '%1$s' ha proprietario errato o autorizzazioni errate. Qualsiasi alias ​​attualmente memorizzato in '%2$s' non sarà disponibile per l'autenticazione"
-alias.dir.notadir = "La directory dell'archivio di alias "%1$s" esiste ma non è una directory"
+alias.dir.notadir = "La directory dell'archivio di alias '%1$s' esiste ma non è una directory"
-alias.dir.renamefail =
- "Impossibile rinominare la directory dell'archivio di alias sospetta da "%1$s" a "%2$s""
+alias.dir.renamefail = "Impossibile rinominare la directory dell'archivio di alias sospetta da '%1$s' a '%2$s'"
-alias.alias.badfile =
- "L'archivio di alias "%1$s" esiste ma non è un file regolare. "
- "Gli alias per l'utente "%2$s" non saranno disponibili per "
- "l'autenticazione"
+alias.alias.badfile = "L'archivio alias '%1$s' esiste ma non è un file regolare. Gli alias per l'utente '%2$s' non saranno disponibili per l'autenticazione"
-alias.alias.badperm =
- "L'archivio di alias "%1$s" ha un proprietario o autorizzazioni"
- " errate. "
- "Gli alias per l'utente "%2$s" non saranno disponibili "
- "per l'autenticazione"
+alias.alias.badperm = "L'archivio di alias '%1$s' ha un proprietario errato o autorizzazioni errate. Gli alias per l'utente '%2$s' non saranno disponibili per l'autenticazione"
+alias.alias.rename = "Archivio di alias sospetti '%1$s' rinominato in '%2$s'"
-alias.alias.rename = "Archivio di alias sospetti "%1$s" rinominato in "%2$s""
+alias.alias.renamefail = "Impossibile rinominare l'archivio di alias sospetti da '%1$s' a '%2$s'"
-alias.alias.renamefail =
- "Impossibile rinominare l'archivio di alias sospetti da "%1$s" a "%2$s""
+alias.mapfile.badperm = "Il file di mappatura dell'archivio di alias '%1$s' ha un proprietario errato o autorizzazioni errate. Gli alias ​​nel file di mappatura non saranno disponibili per l'autenticazione"
-alias.mapfile.badperm =
- "Il file di mappatura dell'archivio di alias "%1$s" ha un proprietario"
- " o autorizzazioni errate. "
- "Gli alias nel file di mappatura non saranno "
- "disponibili per l'autenticazione"
+alias.mapping.badfile = "Il file di mappatura '%1$s' esiste ma non è un file regolare. Gli alias ​​nel file di mappatura non saranno disponibili per l'autenticazione"
-alias.mapping.badfile =
- "Il file di mappatura "%1$s" esiste ma non è un file regolare. "
- "Gli alias nel file di mappatura non saranno "
- "disponibili per l'autenticazione"
-
-alias.removeid =
- "Alias rimosso dall'archivio di alias di proprietà di "%1$s" dall'utente "%2$s""
+alias.removeid = "Alias rimosso dall'archivio di alias di proprietà di '%1$s' dall'utente '%2$s'"
diff --git a/open-vm-tools/vgauth/service/l10n/ja.vmsg b/open-vm-tools/vgauth/service/l10n/ja.vmsg
index abd6c4d2..fbdc5049 100644
--- a/open-vm-tools/vgauth/service/l10n/ja.vmsg
+++ b/open-vm-tools/vgauth/service/l10n/ja.vmsg
@@ -16,31 +16,31 @@
#
##########################################################
-proto.attack = "セキュリティ攻撃ã®å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚è¦æ±‚タイプ %1$d ã«ã¯ userName (%2$s) ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ãŒã€ã“ã‚Œã¯ãƒ‘イプ所有者 (%3$s) ã¨ä¸€è‡´ã—ã¾ã›ã‚“"
+proto.attack = "セキュリティ アタックã§ã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™! è¦æ±‚ã®ç¨®é¡ž %1$d ã«ã¯ã€ãƒ‘イプã®æ‰€æœ‰è€… (%3$s) ã¨ä¸€è‡´ã—ãªã„ユーザーå (%2$s) ãŒå«ã¾ã‚Œã¦ã„ã¾ã™!"
-validate.samlBearer.fail = "SAML 無記åトークンã®æ¤œè¨¼ãŒå¤±æ•—ã—ã¾ã—ãŸ: %1$d"
+validate.samlBearer.fail = "SAML ä¼é€ãƒˆãƒ¼ã‚¯ãƒ³ã®æ¤œè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸ: %1$d"
-validate.samlBearer.success = "ユーザー「%1$sã€ã® SAML ベアラ トークンãŒæ¤œè¨¼ã•ã‚Œã¾ã—ãŸ"
+validate.samlBearer.success = "ユーザー '%1$s' ã® SAML ä¼é€ãƒˆãƒ¼ã‚¯ãƒ³ãŒæ¤œè¨¼ã•ã‚Œã¾ã—ãŸ"
-alias.addid = "ユーザー「%2$sã€ã«ã‚ˆã‚Šã€Œ%1$sã€ã§æ‰€æœ‰ã•ã‚Œã¦ã„るエイリアス ストアã«ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãŒè¿½åŠ ã•ã‚Œã¾ã—ãŸ"
+alias.addid = "'%1$s' ãŒæ‰€æœ‰ã™ã‚‹ã‚¨ã‚¤ãƒªã‚¢ã‚¹ ストアã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ '%2$s' ã«ã‚ˆã£ã¦ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãŒè¿½åŠ ã•ã‚Œã¾ã—ãŸ"
-alias.dir.badperm = "エイリアス ストア ディレクトリ「%1$sã€ã®æ‰€æœ‰è€…ã¾ãŸã¯æ¨©é™ãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。「%2$sã€ã«ç¾åœ¨ä¿å­˜ã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
+alias.dir.badperm = "エイリアス ストア ディレクトリ '%1$s' ã®æ‰€æœ‰è€…ã¾ãŸã¯æ¨©é™ãŒé©åˆ‡ã§ã¯ã‚ã‚Šã¾ã›ã‚“。'%2$s' ã«ç¾åœ¨æ ¼ç´ã•ã‚Œã¦ã„るエイリアスã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
-alias.dir.notadir = "エイリアス ストア ディレクトリ「%1$sã€ã¯å­˜åœ¨ã—ã¾ã™ãŒã€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã¯ã‚ã‚Šã¾ã›ã‚“"
+alias.dir.notadir = "エイリアス ストア ディレクトリ '%1$s' ã¯å­˜åœ¨ã—ã¾ã™ãŒã€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã¯ã‚ã‚Šã¾ã›ã‚“"
-alias.dir.renamefail = "ç–‘ã‚ã—ã„エイリアス ストア ディレクトリã®åå‰ã€Œ%1$sã€ã‚’「%2$sã€ã«å¤‰æ›´ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+alias.dir.renamefail = "å•é¡Œã®ã‚るエイリアス ストア ディレクトリã®åå‰ '%1$s' ã‚’ '%2$s' ã«å¤‰æ›´ã§ãã¾ã›ã‚“ã§ã—ãŸ"
-alias.alias.badfile = "エイリアス ストア「%1$sã€ã¯å­˜åœ¨ã—ã¾ã™ãŒã€é€šå¸¸ã®ãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。 ユーザー「%2$sã€ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
+alias.alias.badfile = "エイリアス ストア '%1$s' ã¯å­˜åœ¨ã—ã¾ã™ãŒã€é€šå¸¸ã®ãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。ユーザー '%2$s' ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
-alias.alias.badperm = "エイリアス ストア「%1$sã€ã®æ‰€æœ‰è€…ã¾ãŸã¯æ¨©é™ãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。ユーザー「%2$sã€ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
+alias.alias.badperm = "エイリアス ストア '%1$s' ã®æ‰€æœ‰è€…ã¾ãŸã¯æ¨©é™ãŒé©åˆ‡ã§ã¯ã‚ã‚Šã¾ã›ã‚“。ユーザー '%2$s' ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
-alias.alias.rename = "ç–‘ã‚ã—ã„エイリアス ストアã®åå‰ã€Œ%1$sã€ãŒã€Œ%2$sã€ã«å¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
+alias.alias.rename = "å•é¡Œã®ã‚るエイリアス ストアã®åå‰ '%1$s' ㌠'%2$s' ã«å¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
-alias.alias.renamefail = "ç–‘ã‚ã—ã„エイリアス ストアã®åå‰ã€Œ%1$sã€ã‚’「%2$sã€ã«å¤‰æ›´ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+alias.alias.renamefail = "å•é¡Œã®ã‚るエイリアス ストアã®åå‰ '%1$s' ã‚’ '%2$s' ã«å¤‰æ›´ã§ãã¾ã›ã‚“ã§ã—ãŸ"
-alias.mapfile.badperm = "エイリアス ストア マッピング ファイル「%1$sã€ã®æ‰€æœ‰è€…ã¾ãŸã¯æ¨©é™ãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。マッピング ファイル内ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
+alias.mapfile.badperm = "エイリアス ストア マッピング ファイル '%1$s' ã®æ‰€æœ‰è€…ã¾ãŸã¯æ¨©é™ãŒé©åˆ‡ã§ã¯ã‚ã‚Šã¾ã›ã‚“。マッピング ファイルã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
-alias.mapping.badfile = "マッピング ファイル「%1$sã€ã¯å­˜åœ¨ã—ã¾ã™ãŒã€é€šå¸¸ã®ãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。マッピング ファイル内ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
+alias.mapping.badfile = "マッピング ファイル '%1$s' ã¯å­˜åœ¨ã—ã¾ã™ãŒã€é€šå¸¸ã®ãƒ•ã‚¡ã‚¤ãƒ«ã§ã¯ã‚ã‚Šã¾ã›ã‚“。マッピング ファイルã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã¯èªè¨¼ã«ä½¿ç”¨ã§ãã¾ã›ã‚“"
-alias.removeid = "ユーザー「%2$sã€ã«ã‚ˆã‚Šã€Œ%1$sã€ã§æ‰€æœ‰ã•ã‚Œã¦ã„るエイリアス ストアã‹ã‚‰ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
+alias.removeid = "エイリアスã¯ã€'%1$s' ãŒæ‰€æœ‰ã™ã‚‹ã‚¨ã‚¤ãƒªã‚¢ã‚¹ ストアã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ '%2$s' ã«ã‚ˆã£ã¦å‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
diff --git a/open-vm-tools/vgauth/service/l10n/ko.vmsg b/open-vm-tools/vgauth/service/l10n/ko.vmsg
index 585adc36..27d087f0 100644
--- a/open-vm-tools/vgauth/service/l10n/ko.vmsg
+++ b/open-vm-tools/vgauth/service/l10n/ko.vmsg
@@ -16,31 +16,31 @@
#
##########################################################
-proto.attack = "잠재ì ì¸ 보안 ê³µê²©ì´ ìžˆìŠµë‹ˆë‹¤. 요청 유형 %1$dì— íŒŒì´í”„ 소유ìž(%3$s)와 ì¼ì¹˜í•˜ì§€ 않는 userName(%2$s)ì´ ìžˆìŠµë‹ˆë‹¤."
+proto.attack = "보안 ê³µê²©ì´ ë°œìƒí•  수 있습니다. 요청 유형 %1$dì— íŒŒì´í”„ 소유ìž(%3$s)와 ì¼ì¹˜í•˜ì§€ 않는 ì‚¬ìš©ìž ì´ë¦„(%2$s)ì´ ìžˆìŠµë‹ˆë‹¤."
-validate.samlBearer.fail = "SAML ë³´ìœ ìž í† í°ì˜ ìœ íš¨ì„±ì„ ê²€ì‚¬í•˜ì§€ 못했습니다(%1$d)."
+validate.samlBearer.fail = "SAML bearer 토í°ì˜ 유효성 ê²€ì‚¬ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. %1$d"
-validate.samlBearer.success = "'%1$s' 사용ìžì— 대한 SAML ë³´ìœ ìž í† í°ì˜ ìœ íš¨ì„±ì„ ê²€ì‚¬í–ˆìŠµë‹ˆë‹¤."
+validate.samlBearer.success = "ì‚¬ìš©ìž '%1$s'ì— ëŒ€í•œ SAML bearer 토í°ì´ 유효한 것으로 확ì¸ë˜ì—ˆìŠµë‹ˆë‹¤."
-alias.addid = "'%1$s'ì´(ê°€) 소유한 별칭 ì €ìž¥ì†Œì— '%2$s' 사용ìžê°€ ë³„ì¹­ì„ ì¶”ê°€í–ˆìŠµë‹ˆë‹¤."
+alias.addid = "ì‚¬ìš©ìž '%2$s'ì´(ê°€) '%1$s'ì´(ê°€) 소유하는 별칭 ì €ìž¥ì†Œì— ë³„ì¹­ì„ ì¶”ê°€í–ˆìŠµë‹ˆë‹¤."
-alias.dir.badperm = "별칭 저장소 디렉토리 '%1$s'ì— ìž˜ëª»ëœ ì†Œìœ ìž ë˜ëŠ” 사용 ê¶Œí•œì´ ìžˆìŠµë‹ˆë‹¤. 현재 '%2$s'ì— ì €ìž¥ëœ ëª¨ë“  ë³„ì¹­ì„ ì¸ì¦ì— 사용할 수 없습니다."
+alias.dir.badperm = "별칭 저장소 디렉토리 '%1$s'ì˜ ì†Œìœ ìžë‚˜ ê¶Œí•œì´ ì˜¬ë°”ë¥´ì§€ 않습니다. 현재 '%2$s'ì— ì €ìž¥ë˜ì–´ 있는 ë³„ì¹­ì„ ì¸ì¦ì— 사용할 수 없습니다."
alias.dir.notadir = "별칭 저장소 디렉토리 '%1$s'ì´(ê°€) 있지만 디렉토리가 아닙니다."
-alias.dir.renamefail = "ì£¼ì˜ ëŒ€ìƒ ë³„ì¹­ 저장소 디렉토리 ì´ë¦„ì„ '%1$s'ì—ì„œ '%2$s'(으)ë¡œ 바꾸지 못했습니다."
+alias.dir.renamefail = "ì˜ì‹¬ìŠ¤ëŸ¬ìš´ 별칭 저장소 디렉토리 ì´ë¦„ '%1$s'ì„(를) '%2$s'(으)ë¡œ 바꾸지 못했습니다."
-alias.alias.badfile = "별칭 저장소 '%1$s'ì´(ê°€) 있지만 ì¼ë°˜ 파ì¼ì´ 아닙니다. '%2$s' 사용ìžì— 대한 ë³„ì¹­ì„ ì¸ì¦ì— 사용할 수 없습니다."
+alias.alias.badfile = "별칭 저장소 '%1$s'ì´(ê°€) 있지만 ì¼ë°˜ 파ì¼ì´ 아닙니다. ì‚¬ìš©ìž '%2$s'ì˜ ë³„ì¹­ì„ ì¸ì¦ì— 사용할 수 없습니다."
-alias.alias.badperm = "별칭 저장소 '%1$s'ì— ìž˜ëª»ëœ ì†Œìœ ìž ë˜ëŠ” 사용 ê¶Œí•œì´ ìžˆìŠµë‹ˆë‹¤. '%2$s' 사용ìžì— 대한 ë³„ì¹­ì„ ì¸ì¦ì— 사용할 수 없습니다."
+alias.alias.badperm = "별칭 저장소 '%1$s'ì˜ ì†Œìœ ìžë‚˜ ê¶Œí•œì´ ì˜¬ë°”ë¥´ì§€ 않습니다. ì‚¬ìš©ìž '%2$s'ì˜ ë³„ì¹­ì„ ì¸ì¦ì— 사용할 수 없습니다."
-alias.alias.rename = "ì£¼ì˜ ëŒ€ìƒ ë³„ì¹­ 저장소 ì´ë¦„ì„ '%1$s'ì—ì„œ '%2$s'(으)ë¡œ 바꾸었습니다."
+alias.alias.rename = "ì˜ì‹¬ìŠ¤ëŸ¬ìš´ 별칭 저장소 '%1$s' ì´ë¦„ì´ '%2$s'(으)ë¡œ 바뀌었습니다."
-alias.alias.renamefail = "ì£¼ì˜ ëŒ€ìƒ ë³„ì¹­ 저장소 ì´ë¦„ì„ '%1$s'ì—ì„œ '%2$s'(으)ë¡œ 바꾸지 못했습니다."
+alias.alias.renamefail = "ì˜ì‹¬ìŠ¤ëŸ¬ìš´ 별칭 저장소 ì´ë¦„ '%1$s'ì„(를) '%2$s'(으)ë¡œ 바꾸지 못했습니다."
-alias.mapfile.badperm = "별칭 저장소 매핑 íŒŒì¼ '%1$s'ì— ìž˜ëª»ëœ ì†Œìœ ìž ë˜ëŠ” 사용 ê¶Œí•œì´ ìžˆìŠµë‹ˆë‹¤. 매핑 파ì¼ì˜ ë³„ì¹­ì„ ì¸ì¦ì— 사용할 수 없습니다."
+alias.mapfile.badperm = "별칭 저장소 매핑 íŒŒì¼ '%1$s'ì˜ ì†Œìœ ìžë‚˜ ê¶Œí•œì´ ì˜¬ë°”ë¥´ì§€ 않습니다. 매핑 파ì¼ì˜ ë³„ì¹­ì„ ì¸ì¦ì— 사용할 수 없습니다."
alias.mapping.badfile = "매핑 íŒŒì¼ '%1$s'ì´(ê°€) 있지만 ì¼ë°˜ 파ì¼ì´ 아닙니다. 매핑 파ì¼ì˜ ë³„ì¹­ì„ ì¸ì¦ì— 사용할 수 없습니다."
-alias.removeid = "'%1$s'ì´(ê°€) 소유한 별칭 저장소ì—ì„œ '%2$s' 사용ìžê°€ ë³„ì¹­ì„ ì œê±°í–ˆìŠµë‹ˆë‹¤."
+alias.removeid = "ì‚¬ìš©ìž '%2$s'ì´(ê°€) '%1$s'ì´(ê°€) 소유하는 별칭 저장소ì—ì„œ ë³„ì¹­ì„ ì œê±°í–ˆìŠµë‹ˆë‹¤."
diff --git a/open-vm-tools/vgauth/service/l10n/zh_CN.vmsg b/open-vm-tools/vgauth/service/l10n/zh_CN.vmsg
index 29117235..415bea4d 100644
--- a/open-vm-tools/vgauth/service/l10n/zh_CN.vmsg
+++ b/open-vm-tools/vgauth/service/l10n/zh_CN.vmsg
@@ -16,31 +16,31 @@
#
##########################################################
-proto.attack = "å¯èƒ½å­˜åœ¨å®‰å…¨æ”»å‡»! 请求类型 %1$d 所具有的用户å (%2$s) 与管é“所有者 (%3$s) ä¸ç›¸ç¬¦!"
+proto.attack = "å¯èƒ½å‘生安全攻击! 请求类型 %1$d 具有的 userName (%2$s)与管é“所有者(%3$s)ä¸åŒ¹é…!"
-validate.samlBearer.fail = "SAML æŒæœ‰è€…令牌的验è¯å¤±è´¥: %1$d"
+validate.samlBearer.fail = "SAML æŒæœ‰è€…令牌验è¯å¤±è´¥: %1$d"
-validate.samlBearer.success = "已验è¯äº†ç”¨æˆ·â€œ%1$sâ€çš„ SAML æŒæœ‰è€…令牌"
+validate.samlBearer.success = "已验è¯ç”¨æˆ·â€œ%1$sâ€çš„ SAML æŒæœ‰è€…令牌"
-alias.addid = "用户“%2$sâ€å·²å°†åˆ«å添加至由“%1$sâ€æ‰€æœ‰çš„别å库"
+alias.addid = "用户“%2$sâ€å·²å°†åˆ«å添加到“%1$sâ€æ‹¥æœ‰çš„别å存储中"
-alias.dir.badperm = "别å库目录“%1$sâ€çš„所有者或æƒé™ä¸æ­£ç¡®ã€‚“%2$sâ€ä¸­å½“å‰å­˜å‚¨çš„任何别åå‡ä¸å¯ç”¨äºŽè¿›è¡Œèº«ä»½éªŒè¯"
+alias.dir.badperm = "别å存储目录“%1$sâ€å…·æœ‰ä¸æ­£ç¡®çš„所有者或æƒé™ã€‚无法使用当å‰åœ¨â€œ%2$sâ€ä¸­å­˜å‚¨çš„任何别å进行身份验è¯"
-alias.dir.notadir = "别å库目录“%1$sâ€å·²å­˜åœ¨ï¼Œä½†ä¸æ˜¯ä¸€ä¸ªç›®å½•"
+alias.dir.notadir = "别å存储目录“%1$sâ€å·²å­˜åœ¨ï¼Œä½†ä¸æ˜¯ä¸€ä¸ªç›®å½•"
-alias.dir.renamefail = "未能将å¯ç–‘的别å库目录“%1$sâ€é‡å‘½å为“%2$sâ€"
+alias.dir.renamefail = "无法将å¯ç–‘别å存储目录“%1$sâ€é‡å‘½å为“%2$sâ€"
-alias.alias.badfile = "别å库“%1$sâ€å·²å­˜åœ¨ï¼Œä½†ä¸æ˜¯ä¸€ä¸ªå¸¸è§„文件。用户“%2$sâ€çš„别åå°†ä¸å¯ç”¨äºŽè¿›è¡Œèº«ä»½éªŒè¯"
+alias.alias.badfile = "别å存储“%1$sâ€å·²å­˜åœ¨ï¼Œä½†ä¸æ˜¯ä¸€ä¸ªå¸¸è§„文件。无法使用用户“%2$sâ€çš„别å进行身份验è¯"
-alias.alias.badperm = "别å库“%1$sâ€çš„所有者或æƒé™ä¸æ­£ç¡®ã€‚用户“%2$sâ€çš„别åå°†ä¸å¯ç”¨äºŽè¿›è¡Œèº«ä»½éªŒè¯"
+alias.alias.badperm = "别å存储“%1$sâ€å…·æœ‰ä¸æ­£ç¡®çš„所有者或æƒé™ã€‚无法使用用户“%2$sâ€çš„别å进行身份验è¯"
-alias.alias.rename = "å¯ç–‘的别å库“%1$sâ€å·²é‡å‘½å为“%2$sâ€"
+alias.alias.rename = "已将å¯ç–‘别å存储“%1$sâ€é‡å‘½å为“%2$sâ€"
-alias.alias.renamefail = "未能将å¯ç–‘的别å库“%1$sâ€é‡å‘½å为“%2$sâ€"
+alias.alias.renamefail = "无法将å¯ç–‘别å存储“%1$sâ€é‡å‘½å为“%2$sâ€"
-alias.mapfile.badperm = "别å库映射文件“%1$sâ€çš„所有者或æƒé™ä¸æ­£ç¡®ã€‚映射文件中的别åå°†ä¸å¯ç”¨äºŽè¿›è¡Œèº«ä»½éªŒè¯"
+alias.mapfile.badperm = "别å存储映射文件“%1$sâ€å…·æœ‰ä¸æ­£ç¡®çš„所有者或æƒé™ã€‚无法使用映射文件中的别å进行身份验è¯"
-alias.mapping.badfile = "映射文件“%1$sâ€å·²å­˜åœ¨ï¼Œä½†ä¸æ˜¯ä¸€ä¸ªå¸¸è§„文件。映射文件中的别åå°†ä¸å¯ç”¨äºŽè¿›è¡Œèº«ä»½éªŒè¯"
+alias.mapping.badfile = "映射文件“%1$sâ€å·²å­˜åœ¨ï¼Œä½†ä¸æ˜¯ä¸€ä¸ªå¸¸è§„文件。无法使用映射文件中的别å进行身份验è¯"
-alias.removeid = "用户“%2$sâ€å·²å°†åˆ«å从“%1$sâ€æ‰€æ‹¥æœ‰çš„别å库中删除"
+alias.removeid = "用户“%2$sâ€å·²ä»Žâ€œ%1$sâ€æ‹¥æœ‰çš„别å存储中删除别å"
diff --git a/open-vm-tools/vgauth/service/log.c b/open-vm-tools/vgauth/service/log.c
index 25d8e3ce..f99562bd 100644
--- a/open-vm-tools/vgauth/service/log.c
+++ b/open-vm-tools/vgauth/service/log.c
@@ -87,6 +87,7 @@ void
Service_SetLogOnStdout(gboolean flag)
{
isLogOnStdout = flag;
+ gVerboseLogging = TRUE;
}
@@ -452,11 +453,13 @@ Service_InitLogging(gboolean haveConsole,
logWantedLevel = DEFAULT_LOG_LEVELS;
} else if (g_ascii_strcasecmp(loglevel, SERVICE_LOGLEVEL_VERBOSE) == 0) {
logWantedLevel = DEFAULT_LOG_LEVELS | G_LOG_LEVEL_DEBUG;
+ gVerboseLogging = TRUE;
} else {
logWantedLevel = DEFAULT_LOG_LEVELS;
#ifdef VMX86_DEBUG
// add DEBUG for obj builds
logWantedLevel |= G_LOG_LEVEL_DEBUG;
+ gVerboseLogging = TRUE;
#endif
Warning("%s: Unrecognized loglevel '%s'\n", __FUNCTION__, loglevel);
}
diff --git a/open-vm-tools/vgauth/serviceImpl/alias.c b/open-vm-tools/vgauth/serviceImpl/alias.c
index 951a9e60..0f4d516a 100644
--- a/open-vm-tools/vgauth/serviceImpl/alias.c
+++ b/open-vm-tools/vgauth/serviceImpl/alias.c
@@ -821,6 +821,8 @@ ServiceLoadFileContentsPosix(const gchar *fileName,
if (ret < 0) {
Warning("%s: failed to read from file %s (%d)\n",
__FUNCTION__, fileName, errno);
+ // XXX audit this?
+ err = VGAUTH_E_FAIL;
g_free(buf);
goto done;
} else if (ret == 0) { // eof
diff --git a/open-vm-tools/vgauth/serviceImpl/service.c b/open-vm-tools/vgauth/serviceImpl/service.c
index 25fbf217..605deef5 100644
--- a/open-vm-tools/vgauth/serviceImpl/service.c
+++ b/open-vm-tools/vgauth/serviceImpl/service.c
@@ -60,6 +60,8 @@ static int reapCheckTime;
PrefHandle gPrefs = NULL;
static gboolean reapTimerRunning = FALSE;
+gboolean gVerboseLogging = FALSE;
+
/*
* The directory where the service binary resides.
*/
diff --git a/open-vm-tools/vgauth/serviceImpl/serviceInt.h b/open-vm-tools/vgauth/serviceImpl/serviceInt.h
index 852c94ba..63fbe2d7 100644
--- a/open-vm-tools/vgauth/serviceImpl/serviceInt.h
+++ b/open-vm-tools/vgauth/serviceImpl/serviceInt.h
@@ -216,6 +216,7 @@ typedef struct _ServiceValidationResultsData {
*/
extern PrefHandle gPrefs;
+extern gboolean gVerboseLogging;
extern char *gInstallDir;
diff --git a/open-vm-tools/vgauth/serviceImpl/ticket.c b/open-vm-tools/vgauth/serviceImpl/ticket.c
index fd545b97..6e868f5d 100644
--- a/open-vm-tools/vgauth/serviceImpl/ticket.c
+++ b/open-vm-tools/vgauth/serviceImpl/ticket.c
@@ -30,6 +30,31 @@
#endif
/*
+ * XXX TODO
+ *
+ * There may be a bug in the ticket implementation.
+ *
+ * Right now, a ticket doesn't care about any expiration details
+ * of the authn method used to create it. This means a bearer
+ * token that expires in 5 minutes could be used to create a ticket
+ * with a far longer expiration time.
+ *
+ * This seems like a possible security problem, and it should instead
+ * try to obey the auth time of the original authn method.
+ *
+ * This may be messy to implement securely, since we currently
+ * lose the expiration date. It could be passed around along with the
+ * Subject and AliasInfo we already store, but a bad client could
+ * cheat -- but a bad client can do other horrible things. Since CreateTicket
+ * can be called as a normal user, this seems hackable.
+ *
+ * Should CreateTicket be restricted to superUser?
+ *
+ * Also -- we currently would support making a ticket from a ticket.
+ * Are there any security concerns here?
+ */
+
+/*
* Debugging flags.
*/
diff --git a/open-vm-tools/vgauth/serviceImpl/verify.c b/open-vm-tools/vgauth/serviceImpl/verify.c
index f9da41dd..0175a046 100644
--- a/open-vm-tools/vgauth/serviceImpl/verify.c
+++ b/open-vm-tools/vgauth/serviceImpl/verify.c
@@ -28,7 +28,6 @@
#include "serviceInt.h"
#include "certverify.h"
-
/*
******************************************************************************
* ServiceInitVerify -- */ /**
@@ -50,7 +49,6 @@ ServiceInitVerify(void)
if (err != VGAUTH_E_OK) {
goto done;
}
-
done:
return err;
}
@@ -189,6 +187,19 @@ ServiceVerifyAndCheckTrustCertChainForSubject(int numCerts,
}
/*
+ * Dump the token cert chain for debugging purposes.
+ */
+ if (gVerboseLogging) {
+ gchar *chainx509;
+
+ for (i = 0; i < numCerts; i++) {
+ chainx509 = CertVerify_CertToX509String(pemCertChain[i]);
+ Debug("%s: Token chain cert #%d:\n%s", __FUNCTION__, i, chainx509);
+ g_free(chainx509);
+ }
+ }
+
+ /*
* Make sure the user exists -- Query supports deleted users
* to allow for cleanup.
*/
@@ -204,6 +215,20 @@ ServiceVerifyAndCheckTrustCertChainForSubject(int numCerts,
}
/*
+ * Dump the store cert chain for debugging purposes.
+ */
+ if (gVerboseLogging) {
+ gchar *storex509;
+
+ for (i = 0; i < numStoreCerts; i++) {
+ storex509 = CertVerify_CertToX509String(aList[i].pemCert);
+ Debug("%s: Store chain cert #%d:\n%s", __FUNCTION__, i, storex509);
+ g_free(storex509);
+ }
+ }
+
+
+ /*
* Split the incoming chain into trusted and untrusted certs
*/
for (i = 0; i < numCerts; i++) {
diff --git a/open-vm-tools/vmhgfs-fuse/COPYING b/open-vm-tools/vmhgfs-fuse/COPYING
new file mode 100644
index 00000000..09f465ab
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/COPYING
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/open-vm-tools/vmhgfs-fuse/Makefile.am b/open-vm-tools/vmhgfs-fuse/Makefile.am
new file mode 100644
index 00000000..1e076f39
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/Makefile.am
@@ -0,0 +1,55 @@
+################################################################################
+### Copyright (C) 2015 VMware, Inc. All rights reserved.
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of version 2 of the GNU General Public License as
+### published by the Free Software Foundation.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+################################################################################
+
+bin_PROGRAMS = vmhgfs-fuse
+
+AM_CFLAGS =
+AM_CFLAGS += @FUSE_CPPFLAGS@
+AM_CFLAGS += @GLIB2_CPPFLAGS@
+
+vmhgfs_fuse_LDADD =
+vmhgfs_fuse_LDADD += @FUSE_LIBS@
+vmhgfs_fuse_LDADD += @GLIB2_LIBS@
+
+# The linker processes the libraries in sequence, and order matters here.
+vmhgfs_fuse_LDADD += ../lib/hgfs/libHgfs.la
+vmhgfs_fuse_LDADD += ../lib/hgfsBd/libHgfsBd.la
+vmhgfs_fuse_LDADD += ../lib/rpcOut/libRpcOut.la
+vmhgfs_fuse_LDADD += ../lib/message/libMessage.la
+vmhgfs_fuse_LDADD += ../lib/backdoor/libBackdoor.la
+
+vmhgfs_fuse_LDADD += ../lib/string/libString.la
+
+vmhgfs_fuse_SOURCES =
+vmhgfs_fuse_SOURCES += bdhandler.c
+vmhgfs_fuse_SOURCES += cache.c
+vmhgfs_fuse_SOURCES += config.c
+vmhgfs_fuse_SOURCES += dir.c
+vmhgfs_fuse_SOURCES += file.c
+vmhgfs_fuse_SOURCES += filesystem.c
+vmhgfs_fuse_SOURCES += fsutil.c
+vmhgfs_fuse_SOURCES += link.c
+vmhgfs_fuse_SOURCES += main.c
+vmhgfs_fuse_SOURCES += request.c
+vmhgfs_fuse_SOURCES += session.c
+vmhgfs_fuse_SOURCES += transport.c
+
+#vmhgfs_fuse_SOURCES += stubs.c
+vmhgfs_fuse_SOURCES += $(top_srcdir)/lib/stubs/stub-debug.c
+vmhgfs_fuse_SOURCES += $(top_srcdir)/lib/stubs/stub-log.c
+vmhgfs_fuse_SOURCES += $(top_srcdir)/lib/stubs/stub-panic.c
+
diff --git a/open-vm-tools/vmhgfs-fuse/bdhandler.c b/open-vm-tools/vmhgfs-fuse/bdhandler.c
new file mode 100644
index 00000000..62c489fd
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/bdhandler.c
@@ -0,0 +1,255 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * bdhandler.c --
+ *
+ * Background thread for handling backdoor requests and replies.
+ */
+
+/* Must come before any kernel header file. */
+
+
+#include "bdhandler.h"
+#include "hgfsBd.h"
+#include "hgfsProto.h"
+#include "module.h"
+#include "request.h"
+#include "rpcout.h"
+#include "transport.h"
+#include "vm_assert.h"
+
+static HgfsTransportChannel bdChannel;
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsBdChannelOpen --
+ *
+ * Open the backdoor in an idempotent way.
+ *
+ * Results:
+ * TRUE on success, FALSE on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsBdChannelOpen(HgfsTransportChannel *channel) // IN: Channel
+{
+ Bool ret;
+
+ pthread_mutex_lock(&channel->connLock);
+ switch (channel->status) {
+ case HGFS_CHANNEL_UNINITIALIZED:
+ ret = FALSE;
+ break;
+ case HGFS_CHANNEL_CONNECTED:
+ ret = TRUE;
+ break;
+ case HGFS_CHANNEL_NOTCONNECTED:
+ if (HgfsBd_OpenBackdoor((RpcOut **)&channel->priv)) {
+ LOG(8, ("Backdoor opened.\n"));
+ bdChannel.status = HGFS_CHANNEL_CONNECTED;
+ ret = TRUE;
+ ASSERT(channel->priv != NULL);
+ } else {
+ ret = FALSE;
+ }
+ break;
+ default:
+ ASSERT(0); /* Not reached. */
+ ret = FALSE;
+ }
+
+ pthread_mutex_unlock(&channel->connLock);
+ return ret;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsBdChannelCloseInt --
+ *
+ * Close the backdoor in an idempotent way.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsBdChannelCloseInt(HgfsTransportChannel *channel) // IN: Channel
+{
+ if (channel->status == HGFS_CHANNEL_CONNECTED) {
+ ASSERT(channel->priv != NULL);
+ HgfsBd_CloseBackdoor((RpcOut **)&channel->priv);
+ ASSERT(channel->priv == NULL);
+ channel->status = HGFS_CHANNEL_NOTCONNECTED;
+ }
+ LOG(8, ("Backdoor closed.\n"));
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsBdChannelClose --
+ *
+ * Close the backdoor in an idempotent way.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsBdChannelClose(HgfsTransportChannel *channel) // IN: Channel
+{
+ pthread_mutex_lock(&channel->connLock);
+ HgfsBdChannelCloseInt(channel);
+ pthread_mutex_unlock(&channel->connLock);
+ LOG(8, ("Backdoor closed.\n"));
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsBdChannelSend --
+ *
+ * Send a request via backdoor.
+ *
+ * Results:
+ * 0 on success, negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsBdChannelSend(HgfsTransportChannel *channel, // IN: Channel
+ HgfsReq *req) // IN: request to send
+{
+ char const *replyPacket = NULL;
+ size_t payloadSize;
+ int ret;
+
+ ASSERT(req);
+ ASSERT(req->state == HGFS_REQ_STATE_UNSENT);
+ ASSERT(req->payloadSize <= HGFS_LARGE_PACKET_MAX);
+
+ pthread_mutex_lock(&channel->connLock);
+
+ if (channel->status != HGFS_CHANNEL_CONNECTED) {
+ LOG(6, ("Backdoor not opened.\n"));
+ pthread_mutex_unlock(&channel->connLock);
+ return -ENOTCONN;
+ }
+
+ payloadSize = req->payloadSize;
+ LOG(8, ("Backdoor sending.\n"));
+ ret = HgfsBd_Dispatch(channel->priv, HGFS_REQ_PAYLOAD(req), &payloadSize,
+ &replyPacket);
+ if (ret == 0) {
+ LOG(8, ("Backdoor reply received.\n"));
+ /* Request sent successfully. Copy the reply and wake the client. */
+ ASSERT(replyPacket);
+ HgfsCompleteReq(req, replyPacket, payloadSize);
+ } else {
+ /* Map rpc failure to EIO. */
+ ret = -EIO;
+ }
+
+ pthread_mutex_unlock(&channel->connLock);
+
+ return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsBdChannelExit --
+ *
+ * Tear down the channel.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsBdChannelExit(HgfsTransportChannel *channel) // IN
+{
+ pthread_mutex_lock(&channel->connLock);
+ HgfsBdChannelCloseInt(channel);
+ channel->status = HGFS_CHANNEL_UNINITIALIZED;
+ pthread_mutex_unlock(&channel->connLock);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsBdChannelInit --
+ *
+ * Initialize backdoor channel.
+ *
+ * Results:
+ * Always return pointer to back door channel.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+HgfsTransportChannel*
+HgfsBdChannelInit(void)
+{
+ bdChannel.name = "backdoor";
+ bdChannel.ops.open = HgfsBdChannelOpen;
+ bdChannel.ops.close = HgfsBdChannelClose;
+ bdChannel.ops.send = HgfsBdChannelSend;
+ bdChannel.ops.recv = NULL;
+ bdChannel.ops.exit = HgfsBdChannelExit;
+ bdChannel.priv = NULL;
+ pthread_mutex_init(&bdChannel.connLock, NULL);
+ bdChannel.status = HGFS_CHANNEL_NOTCONNECTED;
+ return &bdChannel;
+}
diff --git a/open-vm-tools/vmhgfs-fuse/bdhandler.h b/open-vm-tools/vmhgfs-fuse/bdhandler.h
new file mode 100644
index 00000000..3989281f
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/bdhandler.h
@@ -0,0 +1,32 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * bdhandler.h --
+ *
+ * Backdoor channel implementation.
+ */
+
+#ifndef _HGFS_DRIVER_BDHANDLER_H_
+#define _HGFS_DRIVER_BDHANDLER_H_
+
+#include "transport.h"
+
+HgfsTransportChannel *HgfsBdChannelInit(void);
+
+#endif // _HGFS_DRIVER_BDHANDLER_H_
diff --git a/open-vm-tools/vmhgfs-fuse/cache.c b/open-vm-tools/vmhgfs-fuse/cache.c
new file mode 100644
index 00000000..9da2284f
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/cache.c
@@ -0,0 +1,458 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * cache.c --
+ *
+ * Module-specific components of the vmhgfs driver.
+ */
+#include "module.h"
+#if !defined(__FreeBSD__) && !defined(__SOLARIS__)
+#include <glib.h>
+#endif
+#define CACHE_TIMEOUT 5
+#define CACHE_PURGE_TIME 10
+#define CACHE_PURGE_SLEEP_TIME 30
+#define HASH_THRESHOLD_SIZE (2046 * 4)
+#define HASH_PURGE_SIZE (HASH_THRESHOLD_SIZE / 2)
+#include "cache.h"
+
+/*
+ * HgfsAttrCache, holds an entry for each path
+ */
+
+typedef struct HgfsAttrCache {
+ HgfsAttrInfo attr; /* Attribute of a file or directory */
+ uint64 changeTime; /* time the attribute was last updated */
+ struct list_head list; /* used in linked list implementation */
+ char path[0]; /* path of the file corresponding the the attr */
+} HgfsAttrCache;
+
+
+/* Head of the list */
+struct HgfsAttrCache attrList;
+
+/*Lock for accessing the attribute cache*/
+static pthread_mutex_t HgfsAttrCacheLock = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Lists are used to manage attribute cache in Solaris and FreeBSD,
+ * HashTables are used in Linux. HashTables perform better and hence
+ * once newer version of glib with hash tables are packaged for Solaris
+ * and FreeBSD, this section will go away.
+ */
+
+#if defined(__FreeBSD__) || defined(__SOLARIS__)
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInitCache
+ *
+ * Initializes the list attrList to cache attributes.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ *
+ */
+
+void
+HgfsInitCache()
+{
+ INIT_LIST_HEAD(&attrList.list);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetAttrCache
+ *
+ * Retrieves the attr from the list for a given path.
+ *
+ * Results:
+ * 0 on success else -1 on error
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsGetAttrCache(const char* path, //IN: Path of file or directory
+ HgfsAttrInfo *attr) //IN: Attribute for a given path
+{
+ HgfsAttrCache *tmp;
+ int res = -1;
+ int diff;
+
+ pthread_mutex_lock(&HgfsAttrCacheLock);
+
+ attrList.changeTime = HGFS_GET_TIME(time(NULL));
+ list_for_each_entry(tmp, &attrList.list, list) {
+ LOG(4, ("tmp->path = %d\n", tmp->path));
+ if (strcmp(path, tmp->path) == 0) {
+ LOG(4, ("cache hit. path = %s\n", tmp->path));
+
+ diff = (HGFS_GET_TIME(time(NULL)) - tmp->changeTime) / 10000000;
+
+ LOG(4, ("time since last updated is %d seconds\n", diff));
+ if (diff <= CACHE_TIMEOUT) {
+ *attr = tmp->attr;
+ res = 0;
+ }
+ break;
+ }
+ }
+
+out:
+ pthread_mutex_unlock(&HgfsAttrCacheLock);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsSetAttrCache
+ *
+ * Updates the list with the given (key, attr)pair.
+ *
+ * Results:
+ * 0 on success else negative value on error
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsSetAttrCache(const char* path, //IN: Path of file or directory
+ HgfsAttrInfo *attr) //IN: Attribute for a given path
+{
+ HgfsAttrCache *tmp;
+ int res = 0;
+
+ pthread_mutex_lock(&HgfsAttrCacheLock);
+
+ attrList.changeTime = HGFS_GET_TIME(time(NULL));
+ list_for_each_entry (tmp, &attrList.list, list) {
+ if (strcmp(path, tmp->path) == 0) {
+ tmp->attr = *attr;
+ tmp->changeTime = HGFS_GET_TIME(time(NULL));
+ LOG(4, ("cache entry updated. path = %s\n", tmp->path));
+ goto out;
+ }
+ }
+
+ tmp = malloc(sizeof(HgfsAttrCache) + strlen(path) + 1);
+ if (tmp == NULL) {
+ res = -ENOMEM;
+ goto out;
+ }
+ INIT_LIST_HEAD(&tmp->list);
+ Str_Strcpy(tmp->path, path, strlen(path) + 1);
+ tmp->attr = *attr;
+ tmp->changeTime = HGFS_GET_TIME(time(NULL));
+ list_add(&tmp->list, &attrList.list);
+ LOG(4, ("cache entry added. path = %s\n", tmp->path));
+
+out:
+ pthread_mutex_unlock(&HgfsAttrCacheLock);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInvalidateAttrCache
+ *
+ * Invalidate the attribute list entry for a given path.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+HgfsInvalidateAttrCache(const char* path) //IN: Path to file
+{
+ HgfsAttrCache *tmp;
+
+ pthread_mutex_lock(&HgfsAttrCacheLock);
+
+ list_for_each_entry (tmp, &attrList.list, list) {
+ if (strcmp(path, tmp->path) == 0) {
+ list_del(&tmp->list);
+ free(tmp);
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&HgfsAttrCacheLock);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPurgeCache:
+ *
+ * This routine is called by an independent thread to purge the cache,
+ * deletion is based on time of last update.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void*
+HgfsPurgeCache(void* unused) //IN: Thread argument
+{
+ HgfsAttrCache *tmp;
+ HgfsAttrCache *prev;
+ int diff;
+
+ while (1)
+ {
+ sleep(CACHE_PURGE_SLEEP_TIME);
+
+ pthread_mutex_lock(&HgfsAttrCacheLock);
+
+ list_for_each_entry_safe (tmp, prev, &attrList.list, list) {
+ diff = (HGFS_GET_TIME(time(NULL)) - tmp->changeTime) / 10000000;
+ if (diff > CACHE_PURGE_TIME) {
+ list_del (&tmp->list);
+ free (tmp);
+ }
+ }
+
+ pthread_mutex_unlock(&HgfsAttrCacheLock);
+ }
+ return 0;
+}
+
+#else
+
+
+GHashTable *g_hash_table;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInitCache
+ *
+ * Creates a hash table with string as a key.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *----------------------------------------------------------------------
+ *
+ */
+
+void
+HgfsInitCache()
+{
+ g_hash_table = g_hash_table_new(g_str_hash, g_str_equal);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetAttrCache
+ *
+ * Retrieves the attr from the HashTable for a given path.
+ *
+ * Results:
+ * 0 on success else -1 on error
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsGetAttrCache(const char* path, //IN: Path of file or directory
+ HgfsAttrInfo *attr) //IN: Attribute for a given path
+{
+ HgfsAttrCache *tmp;
+ int res = -1;
+ int diff;
+
+ pthread_mutex_lock(&HgfsAttrCacheLock);
+
+ tmp = (HgfsAttrCache *)g_hash_table_lookup(g_hash_table, path);
+ if (tmp != NULL) {
+ LOG(4, ("cache hit. path = %s\n", tmp->path));
+
+ diff = (HGFS_GET_TIME(time(NULL)) - tmp->changeTime) / 10000000;
+ LOG(4, ("time since last updated is %d seconds\n", diff));
+ if ( diff <= CACHE_TIMEOUT ) {
+ *attr = tmp->attr;
+ res = 0;
+ }
+ }
+
+ pthread_mutex_unlock(&HgfsAttrCacheLock);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsSetAttrCache
+ *
+ * Updates the HashTable with the given (key, attr) pair.
+ *
+ * Results:
+ * 0 on success else negative value on error
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsSetAttrCache(const char* path, //IN: Path of file or directory
+ HgfsAttrInfo *attr) //IN: Attribute for a given path
+{
+ HgfsAttrCache *tmp;
+ int res = 0;
+
+ pthread_mutex_lock(&HgfsAttrCacheLock);
+
+ tmp = (HgfsAttrCache *)g_hash_table_lookup(g_hash_table, path);
+ if (tmp != NULL) {
+ tmp->attr = *attr;
+ tmp->changeTime = HGFS_GET_TIME(time(NULL));
+ goto out;
+ }
+
+ tmp = malloc(sizeof(HgfsAttrCache) + strlen(path) + 1);
+ if (tmp == NULL) {
+ return -ENOMEM;
+ goto out;
+ }
+
+ Str_Strcpy(tmp->path, path, strlen(path) + 1);
+ tmp->attr = *attr;
+ tmp->changeTime = HGFS_GET_TIME(time(NULL));
+
+ g_hash_table_insert(g_hash_table, (gpointer)tmp->path, (gpointer)tmp);
+
+out:
+ pthread_mutex_unlock(&HgfsAttrCacheLock);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsInvalidateAttrCache
+ *
+ * Invalidate the HashTable entry for a path.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+HgfsInvalidateAttrCache(const char* path) //IN: Path to file
+{
+ HgfsAttrCache *tmp;
+
+ pthread_mutex_lock(&HgfsAttrCacheLock);
+ tmp = (HgfsAttrCache *)g_hash_table_lookup(g_hash_table, path);
+ if (tmp != NULL) {
+ tmp->changeTime = 0;
+ }
+ pthread_mutex_unlock(&HgfsAttrCacheLock);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPurgeCache
+ *
+ * This routine is called by an independent thread to purge the cache,
+ * for performance reasons, the deletion is done in random based
+ * on the order of iteration.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void*
+HgfsPurgeCache(void* unused) //IN: Thread argument
+{
+ gpointer key, value;
+ GHashTableIter iter;
+
+ while (1) {
+ sleep(CACHE_PURGE_SLEEP_TIME);
+
+ pthread_mutex_lock(&HgfsAttrCacheLock);
+
+ if (g_hash_table_size(g_hash_table) >= HASH_THRESHOLD_SIZE) {
+ g_hash_table_iter_init(&iter, g_hash_table);
+ while (g_hash_table_iter_next(&iter, &key, &value) &&
+ (g_hash_table_size(g_hash_table) >= HASH_PURGE_SIZE)) {
+ g_hash_table_iter_remove(&iter);
+ free(value);
+ }
+ }
+
+ pthread_mutex_unlock(&HgfsAttrCacheLock);
+ }
+ return 0;
+}
+#endif
diff --git a/open-vm-tools/vmhgfs-fuse/cache.h b/open-vm-tools/vmhgfs-fuse/cache.h
new file mode 100644
index 00000000..332d8e1c
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/cache.h
@@ -0,0 +1,34 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * cache.h --
+ *
+ * Declarations of cache management functions
+ */
+
+#ifndef _HGFS_DRIVER_CACHE_H_
+#define _HGFS_DRIVER_CACHE_H_
+
+int HgfsGetAttrCache(const char* path, HgfsAttrInfo *attr);
+int HgfsSetAttrCache(const char* path, HgfsAttrInfo *attr);
+void HgfsInitCache();
+void* HgfsPurgeCache(void*);
+void HgfsInvalidateAttrCache(const char* path);
+
+#endif
diff --git a/open-vm-tools/vmhgfs-fuse/config.c b/open-vm-tools/vmhgfs-fuse/config.c
new file mode 100644
index 00000000..241c66c6
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/config.c
@@ -0,0 +1,521 @@
+/*********************************************************
+ * Copyright (C) 2015 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * config.c --
+ *
+ */
+
+#include "module.h"
+#include <sys/utsname.h>
+
+#ifdef VMX86_DEVEL
+int LOGLEVEL_THRESHOLD = 4;
+#endif
+
+/* Kernel version as integer macro */
+#define KERNEL_RELEASE(x, y, z) (((x) << 16) | ((y) << 8) | (z))
+
+/*
+ * System state for eligibility for HGFS FUSE to be enabled.
+ * See comments in the Usage function which must match the enum
+ * and messages table below.
+ */
+
+#define HGFS_DEFS \
+ DEFINE_HFGS_DEF(HGFS_SYSCOMPAT_FUSE_ENABLED, "HGFS FUSE client enabled") \
+ DEFINE_HFGS_DEF(HGFS_SYSCOMPAT_OS_NOT_SUPPORTED, "HGFS FUSE client not supported for this OS version") \
+ DEFINE_HFGS_DEF(HGFS_SYSCOMPAT_OS_NO_FUSE, "HGFS FUSE client needs FUSE environment")
+
+#undef DEFINE_HFGS_DEF
+
+#define DEFINE_HFGS_DEF(a, b) a,
+
+typedef enum {
+ HGFS_DEFS
+} HgfsSystemCompatibility;
+
+#undef DEFINE_HFGS_DEF
+
+#define DEFINE_HFGS_DEF(a, b) b,
+
+const char *HgfsSystemCompatibilityMsg[] = {
+ HGFS_DEFS
+};
+
+#undef DEFINE_HFGS_DEF
+
+enum {
+ KEY_HELP,
+ KEY_VERSION,
+ KEY_BIG_WRITES,
+ KEY_NO_BIG_WRITES,
+ KEY_ENABLED_FUSE,
+};
+
+#define VMHGFS_OPT(t, p, v) { t, offsetof(struct vmhgfsConfig, p), v }
+
+const struct fuse_opt vmhgfsOpts[] = {
+#ifdef VMX86_DEVEL
+ VMHGFS_OPT("--loglevel %i", logLevel, 4),
+ VMHGFS_OPT("-l %i", logLevel, 4),
+#endif
+ /* We will change the default value, unless it is specified explicitly. */
+ FUSE_OPT_KEY("big_writes", KEY_BIG_WRITES),
+ FUSE_OPT_KEY("nobig_writes", KEY_NO_BIG_WRITES),
+
+ FUSE_OPT_KEY("-V", KEY_VERSION),
+ FUSE_OPT_KEY("--version", KEY_VERSION),
+ FUSE_OPT_KEY("-h", KEY_HELP),
+ FUSE_OPT_KEY("--help", KEY_HELP),
+ FUSE_OPT_KEY("-e", KEY_ENABLED_FUSE),
+ FUSE_OPT_KEY("--enabled", KEY_ENABLED_FUSE),
+ FUSE_OPT_END
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Usage
+ *
+ * Show Usage.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+Usage(char *prog_name) // IN
+{
+ fprintf(stderr,
+ "Usage:\t%s sharedir mountpoint [options]\nExamples:\n"
+ "\t%s .host:/ /mnt/hgfs\n"
+ "\t%s .host:/foo/bar /mnt/bar\n\n"
+ "general options:\n"
+ " -o opt,[opt...] mount options\n"
+ " -h --help print help\n"
+ " -V --version print version\n"
+ " -e --enabled check if system is enabled\n"
+ " for the HGFS FUSE client. Exits with:\n"
+ " 0 - system is enabled for HGFS FUSE\n"
+ " 1 - system OS version is not supported for HGFS FUSE\n"
+ " 2 - system needs FUSE packages for HGFS FUSE\n"
+ "\n"
+#ifdef VMX86_DEVEL
+ "vmhgfs options:\n"
+ " -l --loglevel NUM set loglevel=NUM only available in debug build.\n"
+ "\n"
+#endif
+ , prog_name, prog_name, prog_name);
+}
+
+#define LIB_MODULEPATH "/lib/modules"
+#define MODULES_DEP "modules.dep"
+#define FUSER_MOUNT_BIN "/bin/fusermount"
+#define FUSER_MOUNT_USR_BIN "/usr/bin/fusermount"
+#define PROC_FILESYSTEMS "/proc/filesystems"
+#define FUSER_KERNEL_FS "fuse"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SysCompatFusermountCheck
+ *
+ * Test if the FUSE fusermount command is installed.
+ *
+ * Results:
+ * FALSE the HGFS FUSE client is not installed, TRUE if it is installed.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+static Bool
+SysCompatFusermountCheck(void) // IN:
+{
+ Bool fusermountExists = TRUE;
+ int accessResult;
+
+ /*
+ * Check both locations as it varies e.g. SUSE uses "/usr/bin"
+ * and Ubuntu uses "/bin".
+ */
+ accessResult = access(FUSER_MOUNT_BIN, F_OK);
+ if (accessResult == -1) {
+ accessResult = access(FUSER_MOUNT_USR_BIN, F_OK);
+ if (accessResult == -1) {
+ fprintf(stderr, "failed to access %s or %s %d\n",
+ FUSER_MOUNT_BIN, FUSER_MOUNT_USR_BIN, errno);
+ fusermountExists = FALSE;
+ }
+ }
+
+ return fusermountExists;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SysCompatIsInstalledFuse
+ *
+ * Test if the FUSE file system is installed but not yet loaded.
+ *
+ * Results:
+ * FALSE the HGFS FUSE client is not installed, TRUE if it is installed.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+static Bool
+SysCompatIsInstalledFuse(char *utsRelease) // IN: kernel release
+{
+ char *fuseFilesystem;
+ char *modulesDep;
+ char *modulesDepData = NULL;
+ struct stat modulesDepStat;
+ size_t modulesDepLen;
+ size_t modulesDepDataSize;
+ size_t modulesDepFileSize;
+ int modulesDepFd = -1;
+ Bool installedFuse = FALSE;
+ int statResult;
+
+ modulesDep = Str_Asprintf(&modulesDepLen, "%s/%s/%s",
+ LIB_MODULEPATH, utsRelease, MODULES_DEP);
+
+ if (modulesDep == NULL) {
+ fprintf(stderr, "failed to create path str for %s\n", MODULES_DEP);
+ goto exit;
+ }
+
+ modulesDepFd = open(modulesDep, O_RDONLY);
+ if (modulesDepFd == -1) {
+ fprintf(stderr, "failed to open %s %d\n", modulesDep, errno);
+ goto exit;
+ }
+
+ statResult = fstat(modulesDepFd, &modulesDepStat);
+ if (statResult == -1) {
+ fprintf(stderr, "failed to stat %s %d\n", modulesDep, errno);
+ goto exit;
+ }
+ modulesDepFileSize = (size_t)modulesDepStat.st_size;
+ modulesDepData = malloc(modulesDepFileSize + 1);
+ if (modulesDepData == NULL) {
+ fprintf(stderr, "failed to alloc data buf for %s\n", modulesDep);
+ goto exit;
+ }
+
+ modulesDepDataSize = read(modulesDepFd,
+ modulesDepData,
+ modulesDepFileSize);
+
+ if (modulesDepDataSize != modulesDepFileSize) {
+ fprintf(stderr, "failed to read %s %d\n", modulesDep, errno);
+ goto exit;
+ }
+
+ modulesDepData[modulesDepDataSize] = '\0';
+ fuseFilesystem = strstr(modulesDepData,
+ FUSER_KERNEL_FS);
+
+ installedFuse = (fuseFilesystem != NULL);
+
+exit:
+ if (modulesDepFd != -1) {
+ close(modulesDepFd);
+ }
+ free(modulesDepData);
+ free(modulesDep);
+ return installedFuse;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SysCompatIsRegisteredFuse
+ *
+ * Test if the FUSE file system is registered.
+ *
+ * Results:
+ * FALSE the FUSE is not registered, TRUE if it is.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+static Bool
+SysCompatIsRegisteredFuse(void) // IN
+{
+ Bool registeredFuse = FALSE;
+ int procFilesystemsFd;
+ char procFilesystems[4096];
+ char *fuseFilesystem;
+ ssize_t procFilesystemsDataSize;
+
+ procFilesystemsFd = open(PROC_FILESYSTEMS, O_RDONLY);
+ if (procFilesystemsFd == -1) {
+ fprintf(stderr, "failed to open %s %d\n", PROC_FILESYSTEMS, errno);
+ goto exit;
+ }
+
+ procFilesystemsDataSize = read(procFilesystemsFd,
+ procFilesystems,
+ sizeof procFilesystems - 1);
+
+ if (procFilesystemsDataSize < sizeof FUSER_KERNEL_FS) {
+ fprintf(stderr, "failed to read %s %d\n", PROC_FILESYSTEMS, errno);
+ goto exit;
+ }
+
+ procFilesystems[procFilesystemsDataSize] = '\0';
+ fuseFilesystem = strstr(procFilesystems,
+ FUSER_KERNEL_FS);
+
+
+ registeredFuse = (fuseFilesystem != NULL);
+
+exit:
+ if (procFilesystemsFd != -1) {
+ close(procFilesystemsFd);
+ }
+ return registeredFuse;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SysCompatCheck
+ *
+ * Check if the system is compatible for FUSE.
+ *
+ * Results:
+ * 0 the system compatible so FUSE is enabled,
+ * 1 the system OS version is not supported (disabled)
+ * 2 the system does not have FUSE installed.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+static HgfsSystemCompatibility
+SysCompatCheck(char *prog_name) // IN
+{
+ struct utsname buf;
+ HgfsSystemCompatibility sysCompat = HGFS_SYSCOMPAT_OS_NOT_SUPPORTED;
+ char *utsRelease = NULL;
+ int k[3] = {0};
+ int release;
+
+ if (uname(&buf) == -1) {
+ fprintf(stderr, "%s: failed to retrieve kernel info %d\n", __func__, errno);
+ goto exit;
+ }
+
+ utsRelease = strdup(buf.release);
+
+ if (sscanf(utsRelease, "%d.%d.%d", &k[0], &k[1], &k[2]) == 0) {
+ fprintf(stderr, "%s: failed to extract kernel release\n", __func__);
+ goto exit;
+ } else {
+ release = KERNEL_RELEASE(k[0], k[1], k[2]);
+ }
+
+ if (release < KERNEL_RELEASE(4, 0, 0)) {
+ fprintf(stderr, "%s: incompatible kernel version %02d.%02d.%02d\n",
+ __func__, k[0], k[1], k[2]);
+ goto exit;
+ }
+
+ if (!SysCompatIsRegisteredFuse()) {
+ /* Check if FUSE is installed but not loaded yet. */
+ if (!SysCompatIsInstalledFuse(utsRelease)) {
+ fprintf(stderr, "%s: failed FUSE install checks\n", __func__);
+ sysCompat = HGFS_SYSCOMPAT_OS_NO_FUSE;
+ goto exit;
+ }
+ }
+
+ /*
+ * Finally check the system paths to see if the user has the
+ * needed fusemount binary installed.
+ */
+ if (!SysCompatFusermountCheck()) {
+ sysCompat = HGFS_SYSCOMPAT_OS_NO_FUSE;
+ goto exit;
+ }
+
+ sysCompat = HGFS_SYSCOMPAT_FUSE_ENABLED;
+
+exit:
+ free(utsRelease);
+ fprintf(stderr, "%s: %d - %s\n", prog_name, sysCompat,
+ HgfsSystemCompatibilityMsg[sysCompat]);
+ return sysCompat;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * vmhgfsOptProc
+ *
+ * Process options the fuse way. check the fuse document for details.
+ *
+ * Results:
+ * -1 on error, 0 if arg is to be discarded, 1 if arg should be kept
+ *
+ * Side effects:
+ * In KEY_HELP or KEY_VERSION cases, they will be processed and
+ * the process will exit immediately.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+vmhgfsOptProc(void *data, // IN
+ const char *arg, // IN
+ int key, // IN
+ struct fuse_args *outargs) // OUT
+{
+ struct vmhgfsConfig *config = data;
+
+ switch (key) {
+ case FUSE_OPT_KEY_NONOPT:
+ if (!gState->basePath &&
+ strncmp(arg, HOSTNAME_PREFIX, strlen(HOSTNAME_PREFIX)) == 0) {
+ const char *p = arg + strlen(HOSTNAME_PREFIX);
+ char *q;
+
+ /*
+ * remove hostname and trailing spaces. e.g.
+ * ".host:/" => ""
+ * ".host:/abc/" => "/abc"
+ */
+ gState->basePath = strdup(p);
+ q = gState->basePath + strlen(gState->basePath) - 1;
+ if (*q == '/' && q >= gState->basePath) {
+ *q = '\0';
+ }
+ gState->basePathLen = strlen(gState->basePath);
+ if (gState->basePathLen == 0) {
+ free(gState->basePath);
+ gState->basePath = NULL;
+ }
+ return 0;
+ }
+ return 1;
+
+ case KEY_BIG_WRITES:
+ config->addBigWrites = TRUE;
+ return 0;
+
+ case KEY_NO_BIG_WRITES:
+ config->addBigWrites = FALSE;
+ return 0;
+
+ case KEY_HELP:
+ Usage(outargs->argv[0]);
+ fuse_opt_add_arg(outargs, "-ho");
+ fuse_main(outargs->argc, outargs->argv, NULL, NULL);
+ exit(1);
+
+ case KEY_ENABLED_FUSE: {
+ HgfsSystemCompatibility sysCompat;
+ sysCompat = SysCompatCheck(outargs->argv[0]);
+ exit(sysCompat);
+ }
+
+ case KEY_VERSION:
+ fprintf(stderr, "%s: version %s\n\n", outargs->argv[0],
+ VMHGFS_DRIVER_VERSION_STRING);
+ fuse_opt_add_arg(outargs, "--version");
+ fuse_main(outargs->argc, outargs->argv, NULL, NULL);
+ exit(0);
+ }
+ return 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * vmhgfsPreprocessArgs
+ *
+ * Process arguments we care about before passing them on to fuse.
+ *
+ * Results:
+ * Returns -1 on error, 0 on success.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+vmhgfsPreprocessArgs(struct fuse_args *outargs) // IN/OUT
+{
+ struct vmhgfsConfig config;
+ int res;
+
+ gState->basePath = NULL;
+ gState->basePathLen = 0;
+
+#ifdef VMX86_DEVEL
+ config.logLevel = LOGLEVEL_THRESHOLD;
+#endif
+#ifdef __APPLE__
+ /* osxfuse does not have option 'big_writes'. */
+ config.addBigWrites = FALSE;
+#else
+ config.addBigWrites = TRUE;
+#endif
+
+ res = fuse_opt_parse(outargs, &config, vmhgfsOpts, vmhgfsOptProc);
+ if (res != 0) {
+ goto exit;
+ }
+
+#ifdef VMX86_DEVEL
+ LOGLEVEL_THRESHOLD = config.logLevel;
+#endif
+ /* Default option changes for vmhgfs fuse client. */
+ if (config.addBigWrites) {
+ res = fuse_opt_add_arg(outargs, "-obig_writes");
+ if (res != 0) {
+ goto exit;
+ }
+ }
+
+exit:
+ return res;
+}
diff --git a/open-vm-tools/vmhgfs-fuse/config.h b/open-vm-tools/vmhgfs-fuse/config.h
new file mode 100644
index 00000000..5bc2d13c
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/config.h
@@ -0,0 +1,42 @@
+/*********************************************************
+ * Copyright (C) 2015 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * config.h --
+ *
+ */
+
+#ifndef _VMHGFS_FUSE_CONFIG_H_
+#define _VMHGFS_FUSE_CONFIG_H_
+
+#define HOSTNAME_PREFIX ".host:"
+
+struct vmhgfsConfig {
+#ifdef VMX86_DEVEL
+ int logLevel;
+#endif
+ int addBigWrites;
+ int addAllowOther;
+};
+
+int vmhgfsOptProc(void *data, const char *arg,
+ int key, struct fuse_args *outargs);
+
+int vmhgfsPreprocessArgs(struct fuse_args *outargs);
+
+#endif //_VMHGFS_FUSE_CONFIG_H_
diff --git a/open-vm-tools/vmhgfs-fuse/dir.c b/open-vm-tools/vmhgfs-fuse/dir.c
new file mode 100644
index 00000000..6298a4ea
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/dir.c
@@ -0,0 +1,965 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * dir.c --
+ *
+ * File operations for the hgfs driver.
+ */
+#include "module.h"
+
+
+#define HGFS_CREATE_DIR_MASK (HGFS_CREATE_DIR_VALID_FILE_NAME | \
+ HGFS_CREATE_DIR_VALID_SPECIAL_PERMS | \
+ HGFS_CREATE_DIR_VALID_OWNER_PERMS | \
+ HGFS_CREATE_DIR_VALID_GROUP_PERMS | \
+ HGFS_CREATE_DIR_VALID_OTHER_PERMS)
+
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPackDirOpenRequest --
+ *
+ * Setup the directory open request, depending on the op version.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsPackDirOpenRequest(const char *path, // IN: Path of the dir to open
+ HgfsOp opUsed, // IN: Op to be used
+ HgfsReq *req) // IN/OUT: Packet to write into
+{
+ char *name;
+ unsigned int *nameLength = NULL;
+ size_t reqSize;
+ int result;
+
+ ASSERT(path);
+ ASSERT(req);
+ LOG(4, ("Path = %s \n", path));
+ switch (opUsed) {
+ case HGFS_OP_SEARCH_OPEN_V3: {
+ HgfsRequestSearchOpenV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ /* We'll use these later. */
+ name = requestV3->dirName.name;
+ nameLength = &requestV3->dirName.length;
+ requestV3->dirName.flags = 0;
+ requestV3->dirName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+ requestV3->dirName.fid = HGFS_INVALID_HANDLE;
+ requestV3->reserved = 0;
+ reqSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+ break;
+ }
+
+ case HGFS_OP_SEARCH_OPEN: {
+ HgfsRequestSearchOpen *request;
+
+ request = (HgfsRequestSearchOpen *)(HGFS_REQ_PAYLOAD(req));
+
+ /* We'll use these later. */
+ name = request->dirName.name;
+ nameLength = &request->dirName.length;
+ reqSize = sizeof *request;
+ break;
+ }
+
+ default:
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ return -EPROTO;
+ }
+
+ /* Convert to CP name. */
+
+ LOG(4, ("After buildPath = %s\n", path));
+ result = CPName_ConvertTo(path,
+ HGFS_LARGE_PACKET_MAX - (reqSize - 1),
+ name);
+ if (result < 0) {
+ LOG(4, ("CP conversion failed\n"));
+ return -EINVAL;
+ }
+
+ LOG(4, ("After conversion = %s\n", name));
+
+ *nameLength = (uint32) result;
+ req->payloadSize = reqSize + result;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ return 0;
+}
+
+
+/*
+ * HGFS file operations for directories.
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsDirOpen --
+ *
+ * Called whenever a process opens a directory in our filesystem.
+ *
+ * We send a "Search Open" request to the server. If the Open
+ * succeeds, we store the search handle sent by the server in
+ * the handle parameter so it can be reused later.
+ *
+ * Results:
+ * Returns zero on success, error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsDirOpen(const char* path, // IN: Path of dir to open
+ HgfsHandle* handle) // OUT: Handle to the dir
+{
+ HgfsReq *req;
+ int result;
+ HgfsOp opUsed;
+ HgfsStatus replyStatus;
+ HgfsHandle *replySearch;
+
+ ASSERT(path);
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request.\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+retry:
+ opUsed = hgfsVersionSearchOpen;
+ if (opUsed == HGFS_OP_SEARCH_OPEN_V3) {
+ HgfsReplySearchOpenV3 *requestV3 = HgfsGetReplyPayload(req);
+
+ replySearch = &requestV3->search;
+
+ } else {
+ HgfsReplySearchOpen *request = (HgfsReplySearchOpen *)HGFS_REQ_PAYLOAD(req);
+
+ replySearch = &request->search;
+ }
+
+ result = HgfsPackDirOpenRequest(path, opUsed, req);
+ if (result != 0) {
+ LOG(4, ("Error packing request.\n"));
+ goto out;
+ }
+
+ /* Send the request and process the reply. */
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ /* Get the reply and check return status. */
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ switch (result) {
+ case 0:
+ *handle = *replySearch;
+ LOG(6, ("Set handle to %u\n", *replySearch));
+ break;
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_SEARCH_OPEN_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 1.\n"));
+ hgfsVersionSearchOpen = HGFS_OP_SEARCH_OPEN;
+ goto retry;
+ }
+ LOG(4, ("Server returned error: %d, opUsed = %d\n", result, opUsed));
+ break;
+ default:
+ LOG(4, ("Server returned error: %d\n", result));
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(4, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsReadDirFromReply --
+ *
+ * This function reads directory entries from the reply packet
+ * contained in the specified request structure. It calls filldir
+ * to copy each entry into the vfsDirent buffer.
+ *
+ * For V1 and V2 search read reply, only one entry is returned from
+ * server, while for V3 we may have multiple directory entries. The
+ * number of entries can be read from the reply packet.
+ *
+ * Results:
+ * 0 on success, anything else on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsReadDirFromReply(uint32 *f_pos, // IN/OUT: Offset
+ void *vfsDirent, // OUT: Buffer to copy dentries into
+ fuse_fill_dir_t filldir, // IN: Filler function
+ HgfsReq *req, // IN: The request containing reply
+ HgfsOp opUsed, // IN: request type
+ Bool *done) // OUT: Set true when there are no
+ // more entries
+{
+ uint32 replyCount;
+ HgfsAttrInfo attr;
+ HgfsDirEntry *hgfsDirent = NULL; /* Only for V3. */
+ char *escName = NULL; /* Buffer for escaped version of name */
+ size_t escNameLength = NAME_MAX + 1;
+ int result = 0;
+
+ ASSERT(req);
+
+ escName = malloc(escNameLength);
+ if (!escName) {
+ LOG(4, ("Out of memory allocating escaped name buffer.\n"));
+ return -ENOMEM;
+ }
+
+ replyCount = 1;
+ if (opUsed == HGFS_OP_SEARCH_READ_V3) {
+ HgfsReplySearchReadV3 *replyV3 = HgfsGetReplyPayload(req);
+
+ replyCount = replyV3->count;
+ hgfsDirent = (HgfsDirEntry *)replyV3->payload;
+ if (replyCount == 0) {
+ /* We're at the end of the directory. */
+ *done = TRUE;
+ goto out;
+ }
+ }
+
+ LOG(8, ("Reply counter %u, opUsed %d\n", replyCount, opUsed));
+ while (replyCount-- > 0) {
+ void *rawAttr;
+ char *fileName;
+ uint32 fileNameLength;
+ ino_t ino;
+ uint32 d_type;
+ struct stat st;
+
+ switch(opUsed) {
+ case HGFS_OP_SEARCH_READ_V3: {
+ rawAttr = &hgfsDirent->attr;
+ fileName = hgfsDirent->fileName.name;
+ fileNameLength = hgfsDirent->fileName.length;
+ break;
+ }
+ case HGFS_OP_SEARCH_READ_V2: {
+ HgfsReplySearchReadV2 *replyV2;
+ replyV2 = (HgfsReplySearchReadV2 *)(HGFS_REQ_PAYLOAD(req));
+ rawAttr = &replyV2->attr;
+ fileName = replyV2->fileName.name;
+ fileNameLength = replyV2->fileName.length;
+ break;
+ }
+ case HGFS_OP_SEARCH_READ: {
+ HgfsReplySearchRead *replyV1;
+ replyV1 = (HgfsReplySearchRead *)(HGFS_REQ_PAYLOAD(req));
+ rawAttr = &replyV1->attr;
+ fileName = replyV1->fileName.name;
+ fileNameLength = replyV1->fileName.length;
+ break;
+ }
+ default:
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ result = -EPROTO;
+ goto out;
+ }
+
+ /* Make sure name length is legal. */
+ if (fileNameLength > NAME_MAX) {
+ /*
+ * Skip dentry if its name is too long. We don't try to read next
+ * entry in this reply. It is ok since it happens rarely.
+ */
+ (*f_pos)++;
+ result = -ENAMETOOLONG;
+ goto out;
+ } else if (fileNameLength == 0) {
+ /* We're at the end of the directory. */
+ *done = TRUE;
+ goto out;
+ }
+ result = HgfsUnpackCommonAttr(rawAttr, opUsed, &attr);
+ if (result != 0) {
+ goto out;
+ }
+
+ /*
+ * Escape all non-printable characters (which for linux is just
+ * "/").
+ *
+ * Note that normally we would first need to convert from the
+ * CP name format, but that is done implicitely here since we
+ * are guaranteed to have just one path component per dentry.
+ */
+ result = HgfsEscape_Do(fileName,
+ fileNameLength,
+ escNameLength,
+ escName);
+
+ /*
+ * Check the filename length.
+ *
+ * If the name is too long to be represented in linux, we simply
+ * skip it (i.e., that file is not visible to our filesystem) by
+ * incrementing file->f_pos and repeating the loop to get the
+ * next dentry.
+ *
+ * HgfsEscape_Do returns a negative value if the escaped
+ * output didn't fit in the specified output size, so we can
+ * just check its return value.
+ */
+ if (result < 0) {
+ /*
+ * XXX: Another area where a bad server could cause us to loop
+ * forever.
+ */
+ LOG(4, ("HgfsEscape_Do() returns %d\n", result));
+ (*f_pos)++;
+ continue;
+ }
+
+ /* Reuse fileNameLength to store the filename length after escape. */
+ fileNameLength = result;
+
+ /* Assign the correct dentry type. */
+ switch (attr.type) {
+ case HGFS_FILE_TYPE_SYMLINK:
+ d_type = DT_LNK;
+ break;
+ case HGFS_FILE_TYPE_REGULAR:
+ d_type = DT_REG;
+ break;
+ case HGFS_FILE_TYPE_DIRECTORY:
+ d_type = DT_DIR;
+ break;
+ default:
+ /*
+ * XXX Should never happen. I'd put NOT_IMPLEMENTED() here
+ * but if the driver ever goes in the host it's probably not
+ * a good idea for an attacker to be able to hang the host
+ * simply by using a bogus file type in a reply. [bac]
+ */
+ d_type = DT_UNKNOWN;
+ break;
+ }
+
+ ino = attr.hostFileId;
+ memset(&st, 0, sizeof(st));
+ st.st_blksize = HGFS_BLOCKSIZE;
+ st.st_blocks = HgfsCalcBlockSize(attr.size);
+ st.st_size = attr.size;
+ st.st_ino = ino;
+ st.st_mode = d_type << 12;
+ result = filldir(vfsDirent, escName, &st, 0);
+
+ if (result) {
+ /*
+ * This means that filldir ran out of room in the user buffer
+ * it was copying into; we just break out and return, but
+ * don't increment f_pos. So the next time the user calls
+ * getdents, this dentry will be requested again, will get
+ * retrieved again, and get copied properly to the user.
+ *
+ * The filldir errors are normal when the user buffer is small,
+ * so we return ENOSPC and let the caller treat it specially.
+ */
+ LOG(4, ("filldir() returns %d\n", result));
+ result = -ENOSPC;
+ break;
+ }
+ (*f_pos)++;
+
+ /* For V3, there may be remaining entries to process. */
+ if (opUsed == HGFS_OP_SEARCH_READ_V3) {
+ if (hgfsDirent->nextEntry > 0) {
+ ASSERT(replyCount > 0);
+ }
+ hgfsDirent = (HgfsDirEntry *)((unsigned long)hgfsDirent +
+ hgfsDirent->nextEntry);
+ }
+ }
+
+out:
+ free(escName);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsRequestDirEntries --
+ *
+ * Get the directory entries with the given offset from the server.
+ * The server may return 0, 1, or more than 2 entries depending on
+ * the protocol version.
+ *
+ * Results:
+ * Returns zero on success, negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsRequestDirEntries(HgfsHandle searchHandle, // IN: Handle to dir
+ uint32 offset, // IN: Offset of next dentry to get
+ HgfsReq *req, // IN/OUT: the request
+ HgfsOp *opUsed) // OUT: request type
+{
+ HgfsStatus replyStatus;
+ int result = 0;
+
+ retry:
+ *opUsed = hgfsVersionSearchRead;
+ if (*opUsed == HGFS_OP_SEARCH_READ_V3) {
+ HgfsRequestSearchReadV3 *request = HgfsGetRequestPayload(req);
+
+ request->search = searchHandle;
+ request->offset = offset;
+ request->reserved = 0;
+ request->flags = 0 /* HGFS_SEARCH_READ_FLAG_MULTIPLE_REPLY */;
+ req->payloadSize = sizeof(*request) + HgfsGetRequestHeaderSize();
+
+ } else {
+ HgfsRequestSearchRead *request;
+
+ request = (HgfsRequestSearchRead *)(HGFS_REQ_PAYLOAD(req));
+ request->search = searchHandle;
+ request->offset = offset;
+ req->payloadSize = sizeof *request;
+ }
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, *opUsed);
+
+ /* Send the request and process the reply. */
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ LOG(6, ("Got reply\n"));
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ /* Retry with older version(s). Set globally. */
+ if (result == -EPROTO) {
+ if (*opUsed == HGFS_OP_SEARCH_READ_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 2.\n"));
+ hgfsVersionSearchRead = HGFS_OP_SEARCH_READ_V2;
+ goto retry;
+ } else if (*opUsed == HGFS_OP_SEARCH_READ_V2) {
+ LOG(4, ("Version 2 not supported. Falling back to version 1.\n"));
+ hgfsVersionSearchRead = HGFS_OP_SEARCH_READ;
+ goto retry;
+ }
+ }
+ } else if (result == -EIO) {
+ LOG(4, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsReaddir --
+ *
+ * Handle a readdir request. See details below if interested.
+ *
+ * Readdir is a bit complicated, and is best understood by reading
+ * the code. For the impatient, here is an overview of the major
+ * moving parts [bac]:
+ *
+ * - Getdents syscall calls readdir, which is supposed to call
+ * filldir some number of times.
+ * - Each time it's called, filldir updates a struct with the
+ * number of bytes copied thus far, and sets an error code if
+ * appropriate.
+ * - When readdir returns, getdents checks the struct to see if
+ * any dentries were copied, and if so returns the byte count.
+ * Otherwise, it returns the error from the struct (which should
+ * still be zero if filldir was never called).
+ *
+ * A consequence of this last fact is that if there are no more
+ * dentries, then readdir should NOT call filldir, and should
+ * return from readdir with a non-error.
+ *
+ * Results:
+ * Returns zero if on success, negative error on failure.
+ * (According to /fs/readdir.c, any non-negative return value
+ * means it succeeded).
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsReaddir(HgfsHandle handle, // IN: Directory handle to read from
+ void *dirent, // OUT: Buffer to copy dentries into
+ fuse_fill_dir_t filldir) // IN: Filler function
+{
+ Bool done = FALSE;
+ HgfsReq *request;
+ int result = 0;
+ uint32 f_pos = 0;
+
+ ASSERT(dirent);
+
+ request = HgfsGetNewRequest();
+ if (!request) {
+ LOG(4, ("Out of memory while getting new request\n"));
+ return -ENOMEM;
+ }
+ while (!done) {
+ HgfsOp opUsed;
+ /* Nonzero result = we failed to get valid reply from server. */
+ result = HgfsRequestDirEntries(handle,
+ f_pos,
+ request,
+ &opUsed);
+ if (result) {
+ LOG(4, ("Error getting dentries from server\n"));
+ break;
+ }
+
+ result = HgfsReadDirFromReply(&f_pos, dirent, filldir, request, opUsed,
+ &done);
+
+ LOG(4, ("f_pos = %d\n", f_pos));
+ if (result == -ENAMETOOLONG) {
+ continue;
+ } else if (result == -ENOSPC) {
+ result = 0;
+ break;
+ } else if (result < 0) {
+ LOG(4, ("Error reading dentries from reply packet. Return %d\n", result));
+ break;
+ }
+ }
+
+ if (done == TRUE) {
+ LOG(6, ("End of dir reached.\n"));
+ }
+ HgfsFreeRequest(request);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPackCreateDirRequest --
+ *
+ * Setup the CreateDir request, depending on the op version.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsPackCreateDirRequest(const char *path,
+ int permsMode, // IN: Mode to assign dir
+ HgfsOp opUsed, // IN: Op to be used.
+ HgfsReq *req) // IN/OUT: Packet to write into
+{
+ char *fileName = NULL;
+ uint32 *fileNameLength;
+ size_t reqSize;
+ int result;
+
+ ASSERT(req);
+
+ switch (opUsed) {
+ case HGFS_OP_CREATE_DIR_V3: {
+ HgfsRequestCreateDirV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ reqSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+ /* We'll use these later. */
+ fileName = requestV3->fileName.name;
+ fileNameLength = &requestV3->fileName.length;
+ requestV3->fileName.flags = 0;
+ requestV3->fileName.fid = HGFS_INVALID_HANDLE;
+ requestV3->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+
+ requestV3->mask = HGFS_CREATE_DIR_MASK;
+
+ /* Set permissions. */
+ requestV3->specialPerms = (permsMode & (S_ISUID | S_ISGID | S_ISVTX)) >> 9;
+ requestV3->ownerPerms = (permsMode & S_IRWXU) >> 6;
+ requestV3->groupPerms = (permsMode & S_IRWXG) >> 3;
+ requestV3->otherPerms = (permsMode & S_IRWXO);
+ requestV3->fileAttr = 0;
+ break;
+ }
+ case HGFS_OP_CREATE_DIR_V2: {
+ HgfsRequestCreateDirV2 *requestV2;
+
+ requestV2 = (HgfsRequestCreateDirV2 *)(HGFS_REQ_PAYLOAD(req));
+
+ /* We'll use these later. */
+ fileName = requestV2->fileName.name;
+ fileNameLength = &requestV2->fileName.length;
+ reqSize = sizeof *requestV2;
+
+ requestV2->mask = HGFS_CREATE_DIR_MASK;
+
+ /* Set permissions. */
+ requestV2->specialPerms = (permsMode & (S_ISUID | S_ISGID | S_ISVTX)) >> 9;
+ requestV2->ownerPerms = (permsMode & S_IRWXU) >> 6;
+ requestV2->groupPerms = (permsMode & S_IRWXG) >> 3;
+ requestV2->otherPerms = (permsMode & S_IRWXO);
+ break;
+ }
+ case HGFS_OP_CREATE_DIR: {
+ HgfsRequestCreateDir *request;
+
+ request = (HgfsRequestCreateDir *)(HGFS_REQ_PAYLOAD(req));
+
+ /* We'll use these later. */
+ fileName = request->fileName.name;
+ fileNameLength = &request->fileName.length;
+ reqSize = sizeof *request;
+
+ /* Set permissions. */
+ request->permissions = (permsMode & S_IRWXU) >> 6;
+ break;
+ }
+ default:
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ return -EPROTO;
+ }
+
+
+ /* Convert to CP name. */
+ result = CPName_ConvertTo(path,
+ HGFS_LARGE_PACKET_MAX - (reqSize - 1),
+ fileName);
+ if (result < 0) {
+ LOG(4, ("CP conversion failed.\n"));
+ return -EINVAL;
+ }
+
+ *fileNameLength = result;
+ req->payloadSize = reqSize + result;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsMkdir --
+ *
+ * Handle a mkdir request
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsMkdir(const char *path, // IN: Path to directory
+ int permsMode) // IN: Mode to set
+{
+ HgfsReq *req;
+ HgfsStatus replyStatus;
+ HgfsOp opUsed;
+ int result = 0;
+
+ ASSERT(path);
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request.\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+retry:
+ opUsed = hgfsVersionCreateDir;
+ result = HgfsPackCreateDirRequest(path, permsMode, opUsed, req);
+ if (result != 0) {
+ LOG(4, ("Error packing request.\n"));
+ goto out;
+ }
+
+ /*
+ * Send the request and process the reply. Since HgfsReplyCreateDirV2 and
+ * HgfsReplyCreateDir are identical, we need no special logic here.
+ */
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ LOG(6, ("Got reply.\n"));
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ switch (result) {
+ case 0:
+ LOG(6, ("Directory created successfully, instantiating dentry.\n"));
+ /*
+ * XXX: When we support hard links, this is a good place to
+ * increment link count of parent dir.
+ */
+ break;
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_CREATE_DIR_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 2.\n"));
+ hgfsVersionCreateDir = HGFS_OP_CREATE_DIR_V2;
+ goto retry;
+ } else if (opUsed == HGFS_OP_CREATE_DIR_V2) {
+ LOG(4, ("Version 2 not supported. Falling back to version 1.\n"));
+ hgfsVersionCreateDir = HGFS_OP_CREATE_DIR;
+ goto retry;
+ }
+
+ /* Fallthrough. */
+ default:
+ LOG(6, ("Directory was not created, error %d\n", result));
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(4, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsDelete --
+ *
+ * Handle both unlink and rmdir requests.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsDelete(const char* path, // IN: Path to file
+ HgfsOp op) // IN: Opcode for file type (file or dir)*/
+{
+ HgfsReq *req = NULL;
+ int result = 0;
+ HgfsStatus replyStatus;
+ char *fileName = NULL;
+ uint32 *fileNameLength;
+ uint32 reqSize;
+ HgfsOp opUsed;
+ HgfsAttrInfo newAttr = {0};
+ HgfsAttrInfo *clearReadOnlyAttr = &newAttr;
+ Bool clearedReadOnly = FALSE;
+
+ if ((op != HGFS_OP_DELETE_FILE) &&
+ (op != HGFS_OP_DELETE_DIR)) {
+ LOG(4, ("Invalid opcode. op = %d\n", op));
+ result = -EINVAL;
+ goto out;
+ }
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request.\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+ retry:
+ if (op == HGFS_OP_DELETE_FILE) {
+ opUsed = hgfsVersionDeleteFile;
+ } else {
+ opUsed = hgfsVersionDeleteDir;
+ }
+
+ if (opUsed == HGFS_OP_DELETE_FILE_V3 ||
+ opUsed == HGFS_OP_DELETE_DIR_V3) {
+ HgfsRequestDeleteV3 *request = HgfsGetRequestPayload(req);
+
+ reqSize = sizeof(*request) + HgfsGetRequestHeaderSize();
+ request->hints = 0;
+ fileName = request->fileName.name;
+ fileNameLength = &request->fileName.length;
+ request->fileName.fid = HGFS_INVALID_HANDLE;
+ request->fileName.flags = 0;
+ request->fileName.caseType = HGFS_FILE_NAME_DEFAULT_CASE;
+ request->reserved = 0;
+
+ } else {
+ HgfsRequestDelete *request;
+
+ request = (HgfsRequestDelete *)(HGFS_REQ_PAYLOAD(req));
+ /* Fill out the request packet. */
+ fileName = request->fileName.name;
+ fileNameLength = &request->fileName.length;
+ reqSize = sizeof *request;
+ }
+
+
+ /* Convert to CP name. */
+ result = CPName_ConvertTo(path,
+ HGFS_NAME_BUFFER_SIZET(HGFS_LARGE_PACKET_MAX, reqSize),
+ fileName);
+ if (result < 0) {
+ LOG(4, ("CP conversion failed.\n"));
+ result = -EINVAL;
+ goto out;
+ }
+
+ *fileNameLength = result;
+ req->payloadSize = reqSize + result;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ result = HgfsSendRequest(req);
+ switch (result) {
+ case 0:
+ LOG(6, ("Got reply\n"));
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ switch (result) {
+
+ case -EACCES:
+ case -EPERM:
+ /*
+ * It's possible that we're talking to a Windows server with
+ * a file marked read-only. Let's try again, after removing
+ * the read-only bit from the file.
+ *
+ * Note, currently existing Windows HGFS servers that are running
+ * shares against NTFS volumes do NOT handle the ACLs when setting
+ * a file as writable. Only the attribute for read only is cleared.
+ * This maybe okay but could be inadequate if the ACLs are read only
+ * for the current user. For those cases, the second attempt will
+ * still fail. The server code should be fixed to address this failing
+ * the set attributes for read only if it cannot do both.
+ *
+ * XXX: I think old servers will send -EPERM here. Is this entirely
+ * safe?
+ */
+ if (!clearedReadOnly) {
+ result = HgfsClearReadOnly(path, clearReadOnlyAttr);
+ if (result == 0) {
+ clearedReadOnly = TRUE;
+ LOG(4, ("removed read-only, retrying delete\n"));
+ goto retry;
+ }
+ LOG(4, ("failed to remove read-only attribute\n"));
+ } else {
+ (void)HgfsRestoreReadOnly(path, clearReadOnlyAttr);
+ LOG(4, ("second attempt failed\n"));
+ }
+ break;
+
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_DELETE_DIR_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 1.\n"));
+ hgfsVersionDeleteDir = HGFS_OP_DELETE_DIR;
+ goto retry;
+ } else if (opUsed == HGFS_OP_DELETE_FILE_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 1.\n"));
+ hgfsVersionDeleteFile = HGFS_OP_DELETE_FILE;
+ goto retry;
+ }
+
+ LOG(4, ("Server returned error: %d\n", result));
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ LOG(4, ("Send returned error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ return result;
+}
diff --git a/open-vm-tools/vmhgfs-fuse/file.c b/open-vm-tools/vmhgfs-fuse/file.c
new file mode 100644
index 00000000..011d93b6
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/file.c
@@ -0,0 +1,1471 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * file.c --
+ *
+ * File operations for the hgfs driver.
+ */
+
+#include "cpName.h"
+#include "hgfsProto.h"
+#include "module.h"
+#include "request.h"
+#include "hgfsUtil.h"
+#include "fsutil.h"
+#include "file.h"
+#include "vm_assert.h"
+#include "vm_basic_types.h"
+
+
+
+static int
+HgfsGetOpenFlags(uint32 flags);
+
+
+/*
+ * Private functions.
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPackOpenRequest --
+ *
+ * Setup the Open request, depending on the op version.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsPackOpenRequest(const char *path, // IN: Path to file
+ struct fuse_file_info *fi, // IN: File info structure
+ mode_t permsMode, // IN: Permissions, in this context
+ HgfsOpenValid mask, // IN: Open validation mask
+ HgfsOp opUsed, // IN: Op to use
+ HgfsReq *req) // IN/OUT: Packet to write into
+{
+ char *name;
+ uint32 *nameLength;
+ size_t reqSize;
+ int result;
+ int openMode, openFlags;
+
+ ASSERT(path);
+ ASSERT(req);
+
+ openMode = HgfsGetOpenMode(fi->flags);
+ if (openMode < 0) {
+ LOG(4, ("Failed to get open mode.\n"));
+ return -EINVAL;
+ }
+ openFlags = HgfsGetOpenFlags(fi->flags);
+ if (openFlags < 0) {
+ LOG(4, ("Failed to get open flags.\n"));
+ return -EINVAL;
+ }
+
+ switch (opUsed) {
+ case HGFS_OP_OPEN_V3: {
+ HgfsRequestOpenV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ reqSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+
+ /* We'll use these later. */
+ name = requestV3->fileName.name;
+ nameLength = &requestV3->fileName.length;
+
+ /* Linux clients need case-sensitive lookups. */
+ requestV3->fileName.flags = 0;
+ requestV3->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+ requestV3->fileName.fid = HGFS_INVALID_HANDLE;
+
+ requestV3->mask = mask;
+ requestV3->mode = openMode;
+ requestV3->flags = openFlags;
+
+ /* Set permissions. */
+ if (requestV3->mask & HGFS_FILE_OPEN_PERMS) {
+ requestV3->specialPerms = (permsMode & (S_ISUID | S_ISGID | S_ISVTX)) >> 9;
+ requestV3->ownerPerms = (permsMode & S_IRWXU) >> 6;
+ requestV3->groupPerms = (permsMode & S_IRWXG) >> 3;
+ requestV3->otherPerms = (permsMode & S_IRWXO);
+ }
+
+ /* XXX: Request no lock for now. */
+ requestV3->desiredLock = HGFS_LOCK_NONE;
+
+ requestV3->reserved1 = 0;
+ requestV3->reserved2 = 0;
+ break;
+ }
+
+ case HGFS_OP_OPEN_V2: {
+ HgfsRequestOpenV2 *requestV2;
+
+ requestV2 = (HgfsRequestOpenV2 *)(HGFS_REQ_PAYLOAD(req));
+
+ /* We'll use these later. */
+ name = requestV2->fileName.name;
+ nameLength = &requestV2->fileName.length;
+ reqSize = sizeof *requestV2;
+
+ requestV2->mask = mask;
+ requestV2->mode = openMode;
+ requestV2->flags = openFlags;
+
+ /* Set permissions, requires discussion... default, will set max permission*/
+ if (requestV2->mask & HGFS_FILE_OPEN_PERMS) {
+ requestV2->specialPerms = (permsMode & (S_ISUID | S_ISGID | S_ISVTX)) >> 9;
+ requestV2->ownerPerms = (permsMode & S_IRWXU) >> 6;
+ requestV2->groupPerms = (permsMode & S_IRWXG) >> 3;
+ requestV2->otherPerms = (permsMode & S_IRWXO);
+ }
+
+ /* XXX: Request no lock for now. */
+ requestV2->desiredLock = HGFS_LOCK_NONE;
+ break;
+ }
+ case HGFS_OP_OPEN: {
+ HgfsRequestOpen *request;
+
+ request = (HgfsRequestOpen *)(HGFS_REQ_PAYLOAD(req));
+ /* We'll use these later. */
+ name = request->fileName.name;
+ nameLength = &request->fileName.length;
+ reqSize = sizeof *request;
+
+ request->mode = openMode;
+ request->flags = openFlags;
+
+ /* Set permissions. */
+ request->permissions = (permsMode & S_IRWXU) >> 6;
+ break;
+ }
+ default:
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ return -EPROTO;
+ }
+
+
+ /* Convert to CP name. */
+ result = CPName_ConvertTo(path,
+ HGFS_LARGE_PACKET_MAX - (reqSize - 1),
+ name);
+ if (result < 0) {
+ LOG(4, ("CP conversion failed.\n"));
+ return -EINVAL;
+ }
+
+ *nameLength = (uint32) result;
+ req->payloadSize = reqSize + result;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsUnpackOpenReply --
+ *
+ * Get interesting fields out of the Open reply, depending on the op
+ * version.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsUnpackOpenReply(HgfsReq *req, // IN: Packet with reply inside
+ HgfsOp opUsed, // IN: What request op did we send
+ HgfsHandle *file, // OUT: Handle in reply packet
+ HgfsLockType *lock) // OUT: The server lock we got
+{
+ HgfsReplyOpenV3 *replyV3;
+ HgfsReplyOpenV2 *replyV2;
+ HgfsReplyOpen *replyV1;
+ size_t replySize;
+
+ ASSERT(req);
+ ASSERT(file);
+ ASSERT(lock);
+
+ switch (opUsed) {
+ case HGFS_OP_OPEN_V3:
+ replyV3 = HgfsGetReplyPayload(req);
+ replySize = sizeof(*replyV3) + HgfsGetReplyHeaderSize();
+ *file = replyV3->file;
+ *lock = replyV3->acquiredLock;
+ break;
+ case HGFS_OP_OPEN_V2:
+ replyV2 = (HgfsReplyOpenV2 *)(HGFS_REQ_PAYLOAD(req));
+ replySize = sizeof *replyV2;
+ *file = replyV2->file;
+ *lock = replyV2->acquiredLock;
+ break;
+ case HGFS_OP_OPEN:
+ replyV1 = (HgfsReplyOpen *)(HGFS_REQ_PAYLOAD(req));
+ replySize = sizeof *replyV1;
+ *file = replyV1->file;
+ *lock = HGFS_LOCK_NONE;
+ break;
+ default:
+
+ /* This really shouldn't happen since we set opUsed ourselves. */
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ ASSERT(FALSE);
+ return -EPROTO;
+ }
+
+ if (opUsed < HGFS_OP_OPEN_V3 && req->payloadSize != replySize) {
+ /*
+ * The reply to Open is a fixed size. So the size of the payload
+ * really ought to match the expected size of an HgfsReplyOpen[V2].
+ */
+ LOG(4, ("Wrong packet size.\n"));
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetOpenFlags --
+ *
+ * Based on the flags requested by the process making the open()
+ * syscall, determine which flags to send to the server to open the
+ * file.
+ *
+ * Results:
+ * Returns the correct HgfsOpenFlags enumeration to send to the
+ * server, or -1 on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsGetOpenFlags(uint32 flags) // IN: Open flags
+{
+ uint32 mask = O_CREAT | O_TRUNC | O_EXCL;
+ int result = -1;
+
+ LOG(6, ("Entered\n"));
+
+ /*
+ * Mask the flags to only look at O_CREAT, O_EXCL, and O_TRUNC.
+ */
+
+ flags &= mask;
+
+ /* O_EXCL has no meaning if O_CREAT is not set. */
+ if (!(flags & O_CREAT)) {
+ flags &= ~O_EXCL;
+ }
+
+ /* Pick the right HgfsOpenFlags. */
+ switch (flags) {
+
+ case 0:
+ /* Regular open; fails if file nonexistant. */
+ result = HGFS_OPEN;
+ break;
+
+ case O_CREAT:
+ /* Create file; if it exists already just open it. */
+ result = HGFS_OPEN_CREATE;
+ break;
+
+ case O_TRUNC:
+ /* Truncate existing file; fails if nonexistant. */
+ result = HGFS_OPEN_EMPTY;
+ break;
+
+ case (O_CREAT | O_EXCL):
+ /* Create file; fail if it exists already. */
+ result = HGFS_OPEN_CREATE_SAFE;
+ break;
+
+ case (O_CREAT | O_TRUNC):
+ /* Create file; if it exists already, truncate it. */
+ result = HGFS_OPEN_CREATE_EMPTY;
+ break;
+
+ default:
+ /*
+ * This can only happen if all three flags are set, which
+ * conceptually makes no sense because O_EXCL and O_TRUNC are
+ * mutually exclusive if O_CREAT is set.
+ *
+ * However, the open(2) man page doesn't say you can't set all
+ * three flags, and certain apps (*cough* Nautilus *cough*) do
+ * so. To be friendly to those apps, we just silenty drop the
+ * O_TRUNC flag on the assumption that it's safer to honor
+ * O_EXCL.
+ */
+ LOG(4, ("Invalid open flags %o. Ignoring the O_TRUNC flag.\n", flags));
+ result = HGFS_OPEN_CREATE_SAFE;
+ break;
+ }
+
+ return result;
+}
+
+
+/*
+ * HGFS file operations for files.
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsOpenInt --
+ *
+ * We send an "Open" request to the server with the file path
+ * If the Open succeeds, we store the filehandle sent by the server
+ * in the file info struct so it can be accessed by
+ * read/write/close.
+ *
+ * Results:
+ * Returns zero if on success, error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsOpenInt(const char *path, //IN: Path to a file
+ struct fuse_file_info *fi, //OUT: File info structure
+ mode_t permsMode, //IN: Permissions, in this context
+ HgfsOpenValid mask) //IN: Open validation mask
+{
+ HgfsReq *req;
+ HgfsOp opUsed;
+ HgfsStatus replyStatus;
+ HgfsHandle replyFile;
+ HgfsLockType replyLock;
+ int result = 0;
+
+ ASSERT(NULL != path);
+ ASSERT(NULL != fi);
+
+ LOG(4, ("Entry(%s)\n", path));
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request.\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+ fi->fh = HGFS_INVALID_HANDLE;
+
+retry:
+ /*
+ * Set up pointers using the proper struct This lets us check the
+ * version exactly once and use the pointers later.
+ */
+
+ opUsed = hgfsVersionOpen;
+ result = HgfsPackOpenRequest(path, fi, permsMode, mask, opUsed, req);
+ if (result != 0) {
+ LOG(4, ("Error packing request.\n"));
+ goto out;
+ }
+
+ /* Send the request and process the reply. */
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ /* Get the reply and check return status. */
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ switch (result) {
+ case 0:
+ result = HgfsUnpackOpenReply(req, opUsed, &replyFile, &replyLock);
+ if (result != 0) {
+ break;
+ }
+
+ fi->fh = (uint64_t)replyFile;
+ LOG( 4,("Server file handle: %"FMT64"u\n", fi->fh));
+
+ break;
+
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_OPEN_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 2.\n"));
+ hgfsVersionOpen = HGFS_OP_OPEN_V2;
+ goto retry;
+ }
+
+ /* Retry with Version 1 of Open. Set globally. */
+ if (opUsed == HGFS_OP_OPEN_V2) {
+ LOG(4, ("Version 2 not supported. Falling back to version 1.\n"));
+ hgfsVersionOpen = HGFS_OP_OPEN;
+ goto retry;
+ }
+
+ /* Fallthrough. */
+ default:
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(8, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+out:
+ HgfsFreeRequest(req);
+ LOG(4, ("Exit(0x%"FMT64"x -> %d)\n",fi->fh, result));
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsOpen --
+ *
+ * Called whenever a process opens a file in our filesystem.
+ *
+ * Results:
+ * Returns zero if on success, error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsOpen(const char *path, //IN: Path to a file
+ struct fuse_file_info *fi) //OUT: File info structure
+{
+ return HgfsOpenInt(path, fi, 0, HGFS_FILE_OPEN_MASK);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsCreate --
+ *
+ * Called whenever a process request to create a file
+ *
+ * Results:
+ * Returns zero if on success, error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsCreate(const char *path, //IN: Path to a file
+ mode_t permsMode, //IN: Permission to open the file
+ struct fuse_file_info *fi) //OUT: File info structure
+{
+ return HgfsOpenInt(path, fi, permsMode, HGFS_FILE_CREATE_MASK);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsDoRead --
+ *
+ * Do one read request. Called by HgfsRead, possibly multiple times
+ * if the size of the read is too big to be handled by one server request.
+ *
+ * We send a "Read" request to the server with the given handle.
+ *
+ *
+ * Results:
+ * Returns the number of bytes read on success, or an error on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static int
+HgfsDoRead(HgfsHandle handle, // IN: Handle for this file
+ char *buf, // OUT: Buffer to copy data into
+ size_t count, // IN: Number of bytes to read
+ loff_t offset) // IN: Offset at which to read
+{
+ HgfsReq *req;
+ HgfsOp opUsed;
+ int result = 0;
+ uint32 actualSize = 0;
+ char *payload = NULL;
+ HgfsStatus replyStatus;
+
+ ASSERT(NULL != buf);
+
+ LOG(4, ("Entry(handle = %u, 0x%"FMTSZ"x @ 0x%"FMT64"x)\n", handle, count, offset));
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+ retry:
+ opUsed = hgfsVersionRead;
+ if (opUsed == HGFS_OP_READ_V3) {
+ HgfsRequestReadV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ requestV3->file = handle;
+ requestV3->offset = offset;
+ requestV3->requiredSize = count;
+ requestV3->reserved = 0;
+
+ req->payloadSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+
+ } else {
+ HgfsRequestRead *request;
+
+ request = (HgfsRequestRead *)(HGFS_REQ_PAYLOAD(req));
+ request->file = handle;
+ request->offset = offset;
+ request->requiredSize = count;
+ req->payloadSize = sizeof *request;
+ }
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ /* Send the request and process the reply. */
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ /* Get the reply. */
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ switch (result) {
+ case 0:
+ if (opUsed == HGFS_OP_READ_V3) {
+ HgfsReplyReadV3 * replyV3 = HgfsGetReplyPayload(req);
+
+ actualSize = replyV3->actualSize;
+ payload = replyV3->payload;
+
+ } else {
+ actualSize = ((HgfsReplyRead *)HGFS_REQ_PAYLOAD(req))->actualSize;
+ payload = ((HgfsReplyRead *)HGFS_REQ_PAYLOAD(req))->payload;
+ }
+
+ /* Sanity check on read size. */
+ if (actualSize > count) {
+ LOG(4, ("Server reply: read too big!\n"));
+ result = -EPROTO;
+ goto out;
+ }
+
+ if (0 == actualSize) {
+ /* We got no bytes, so don't need to copy to user. */
+ LOG(8, ("Server reply returned zero\n"));
+ result = actualSize;
+ goto out;
+ }
+
+ /* Return result. */
+ memcpy(buf, payload, actualSize);
+ LOG(8, ("Copied %u\n", actualSize));
+ result = actualSize;
+ break;
+
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_READ_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 1.\n"));
+ hgfsVersionRead = HGFS_OP_READ;
+ goto retry;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(8, ("Error: send request timed out\n"));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Error: send request server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Error: send request unknown : %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ LOG(4, ("Exit(%d)\n", result));
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsRead --
+ *
+ * Called whenever a process reads from a file in our filesystem.
+ *
+ * Results:
+ * Returns the number of bytes read on success, or an error on
+ * failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+ssize_t
+HgfsRead(struct fuse_file_info *fi, // IN: File info struct
+ char *buf, // OUT: User buffer to copy data into
+ size_t count, // IN: Number of bytes to read
+ loff_t offset) // IN: Offset at which to read
+{
+ int result = 0;
+ char *buffer = buf;
+ loff_t curOffset = offset;
+ size_t nextCount, remainingCount = count;
+
+ ASSERT(NULL != fi);
+ ASSERT(NULL != buf);
+
+ LOG(4, ("Entry(0x%"FMT64"x 0x%"FMTSZ"x bytes @ 0x%"FMT64"x)\n",
+ fi->fh, count, offset));
+
+ do {
+ nextCount = (remainingCount > HGFS_LARGE_IO_MAX) ?
+ HGFS_LARGE_IO_MAX : remainingCount;
+ LOG(4, ("Issue DoRead(0x%"FMT64"x 0x%"FMTSZ"x bytes @ 0x%"FMT64"x)\n",
+ fi->fh, nextCount, curOffset));
+ result = HgfsDoRead(fi->fh, buffer, nextCount, curOffset);
+ if (result < 0) {
+ LOG(8, ("Error: DoRead: -> %d\n", result));
+ goto out;
+ }
+ remainingCount -= result;
+ curOffset += result;
+ buffer += result;
+
+ } while ((result > 0) && (remainingCount > 0));
+
+ memset(buffer, 0, remainingCount);
+
+ out:
+ LOG(4, ("Exit(%"FMTSZ"d)\n", count - remainingCount));
+ return (count - remainingCount);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsDoWrite --
+ *
+ * Do one write request. Called by HgfsWrite, possibly multiple
+ * times if the size of the write is too big to be handled by one server
+ * request.
+ *
+ * We send a "Write" request to the server with the given handle.
+ *
+ * Results:
+ * Returns the number of bytes written on success, or an error on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsDoWrite(HgfsHandle handle, // IN: Handle for the file
+ const char *buf, // IN: Buffer containing data
+ size_t count, // IN: Number of bytes to write
+ loff_t offset) // IN: Offset to begin writing at
+{
+ HgfsReq *req;
+ int result = 0;
+ HgfsOp opUsed;
+ uint32 requiredSize = 0;
+ uint32 actualSize = 0;
+ char *payload = NULL;
+ uint32 reqSize;
+ HgfsStatus replyStatus;
+
+ ASSERT(buf);
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+ LOG( 4,("handle = %u \n", handle));
+ retry:
+ opUsed = hgfsVersionWrite;
+ if (opUsed == HGFS_OP_WRITE_V3) {
+ HgfsRequestWriteV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ requestV3->file = handle;
+ requestV3->flags = 0;
+ requestV3->offset = offset;
+ requestV3->requiredSize = count;
+ requestV3->reserved = 0;
+ payload = requestV3->payload;
+ requiredSize = requestV3->requiredSize;
+ reqSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+
+ } else {
+ HgfsRequestWrite *request;
+
+ request = (HgfsRequestWrite *)(HGFS_REQ_PAYLOAD(req));
+ request->file = handle;
+ request->flags = 0;
+ request->offset = offset;
+ request->requiredSize = count;
+ payload = request->payload;
+ requiredSize = request->requiredSize;
+ reqSize = sizeof *request;
+ }
+
+ memcpy(payload, buf, requiredSize);
+ req->payloadSize = reqSize + requiredSize - 1;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ /* Send the request and process the reply. */
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ /* Get the reply. */
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ switch (result) {
+ case 0:
+ if (opUsed == HGFS_OP_WRITE_V3) {
+ HgfsReplyWriteV3 * replyV3 = HgfsGetReplyPayload(req);
+
+ actualSize = replyV3->actualSize;
+
+ } else {
+ actualSize = ((HgfsReplyWrite *)HGFS_REQ_PAYLOAD(req))->actualSize;
+ }
+
+ /* Return result. */
+ LOG(6, ("wrote %u bytes\n", actualSize));
+ result = actualSize;
+ break;
+
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_WRITE_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 1.\n"));
+ hgfsVersionWrite = HGFS_OP_WRITE;
+ goto retry;
+ }
+ break;
+
+ default:
+ LOG(4, ("Server returned error: %d\n", result));
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(8, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsWrite --
+ *
+ * Called whenever a process writes to a file in our filesystem.
+ *
+ * Results:
+ * Returns the number of bytes written on success, or an error on
+ * failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+ssize_t
+HgfsWrite(struct fuse_file_info *fi, // IN: File info structure
+ const char *buf, // OUT: User buffer to copy data into
+ size_t count, // IN: Number of bytes to read
+ loff_t offset) // IN: Offset at which to read
+{
+ int result;
+ const char *buffer = buf;
+ loff_t curOffset = offset;
+ size_t nextCount, remainingCount = count;
+
+ ASSERT(NULL != buf);
+ ASSERT(NULL != fi);
+
+ LOG(6, ("Entry(0x%"FMT64"x off bytes 0x%"FMTSZ"x @ 0x%"FMT64"x)\n",
+ fi->fh, count, offset));
+
+ do {
+ nextCount = (remainingCount > HGFS_LARGE_IO_MAX) ?
+ HGFS_LARGE_IO_MAX : remainingCount;
+
+ LOG(4, ("Issue DoWrite(0x%"FMT64"x 0x%"FMTSZ"x bytes @ 0x%"FMT64"x)\n",
+ fi->fh, nextCount, curOffset));
+
+ result = HgfsDoWrite(fi->fh, buffer, nextCount, curOffset);
+ if (result < 0) {
+ LOG(4, ("Error: DoWrite -> %d\n", result));
+ goto out;
+ }
+ remainingCount -= result;
+ curOffset += result;
+ buffer += result;
+
+ } while ((result > 0) && (remainingCount > 0));
+
+out:
+ LOG(6, ("Exit(0x%"FMTSZ"x)\n", count - remainingCount));
+ return (count - remainingCount);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsRename --
+ *
+ * Handle rename requests.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsRename(const char* from, const char* to)
+{
+ HgfsReq *req = NULL;
+ char *oldName;
+ char *newName;
+ uint32 *oldNameLength;
+ uint32 *newNameLength;
+ int result = 0;
+ uint32 reqSize;
+ HgfsOp opUsed;
+ HgfsStatus replyStatus;
+ HgfsAttrInfo newAttr = {0};
+ HgfsAttrInfo *clearReadOnlyAttr = &newAttr;
+ Bool clearedReadOnly = FALSE;
+
+ ASSERT(from);
+ ASSERT(to);
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+retry:
+ opUsed = hgfsVersionRename;
+ if (opUsed == HGFS_OP_RENAME_V3) {
+ HgfsRequestRenameV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ oldName = requestV3->oldName.name;
+ oldNameLength = &requestV3->oldName.length;
+ requestV3->hints = 0;
+ requestV3->oldName.flags = 0;
+ requestV3->oldName.fid = HGFS_INVALID_HANDLE;
+ requestV3->oldName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+ requestV3->reserved = 0;
+ reqSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+ } else {
+ HgfsRequestRename *request = (HgfsRequestRename *)HGFS_REQ_PAYLOAD(req);
+
+ oldName = request->oldName.name;
+ oldNameLength = &request->oldName.length;
+ reqSize = sizeof *request;
+ }
+ /* Convert old name to CP format. */
+ result = CPName_ConvertTo(from,
+ HGFS_NAME_BUFFER_SIZET(HGFS_LARGE_PACKET_MAX, reqSize),
+ oldName);
+ if (result < 0) {
+ LOG(4, ("oldName CP conversion failed\n"));
+ result = -EINVAL;
+ goto out;
+ }
+
+ *oldNameLength = result;
+ reqSize += result;
+
+ /*
+ * Build full new name to send to server.
+ * Note the different buffer length. This is because HgfsRequestRename
+ * contains two filenames, and once we place the first into the packet we
+ * must account for it when determining the amount of buffer available for
+ * the second.
+ */
+ if (opUsed == HGFS_OP_RENAME_V3) {
+ HgfsRequestRenameV3 *requestV3 = HgfsGetRequestPayload(req);
+ HgfsFileNameV3 *newNameP;
+
+ newNameP = (HgfsFileNameV3 *)((char *)&requestV3->oldName +
+ sizeof requestV3->oldName + result);
+ newName = newNameP->name;
+ newNameLength = &newNameP->length;
+ newNameP->flags = 0;
+ newNameP->fid = HGFS_INVALID_HANDLE;
+ newNameP->caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+ } else {
+ HgfsRequestRename *request = (HgfsRequestRename *)HGFS_REQ_PAYLOAD(req);
+ HgfsFileName *newNameP;
+ newNameP = (HgfsFileName *)((char *)&request->oldName +
+ sizeof request->oldName + result);
+ newName = newNameP->name;
+ newNameLength = &newNameP->length;
+ }
+
+ LOG(6, ("New name: \"%s\"\n", newName));
+
+ /* Convert new name to CP format. */
+ result = CPName_ConvertTo(to,
+ HGFS_NAME_BUFFER_SIZET(HGFS_LARGE_PACKET_MAX, reqSize) - result,
+ newName);
+ if (result < 0) {
+ LOG(4, ("newName CP conversion failed\n"));
+ result = -EINVAL;
+ goto out;
+ }
+
+ *newNameLength = result;
+ reqSize += result;
+ req->payloadSize = reqSize;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ result = HgfsSendRequest(req);
+ switch (result) {
+ case 0:
+ LOG(6, ("Got reply\n"));
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ switch (result) {
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_RENAME_V3) {
+ hgfsVersionRename = HGFS_OP_RENAME;
+ goto retry;
+ } else {
+ LOG(4, ("Server returned error: %d\n", result));
+ }
+ break;
+ case -EACCES:
+ case -EPERM:
+ /*
+ * It's possible that we're talking to a Windows server with
+ * a file marked read-only. Let's try again, after removing
+ * the read-only bit from the file.
+ *
+ * Note, currently existing Windows HGFS servers that are running
+ * shares against NTFS volumes do NOT handle the ACLs when setting
+ * a file as writable. Only the attribute for read only is cleared.
+ * This maybe okay but could be inadequate if the ACLs are read only
+ * for the current user. For those cases, the second attempt will
+ * still fail. The server code should be fixed to address this failing
+ * the set attributes for read only if it cannot do both.
+ *
+ * XXX: I think old servers will send -EPERM here. Is this entirely
+ * safe?
+ * We can receive EACCES or EPERM if we don't have the correct
+ * permission on the source file. So lets not assume that we have
+ * a target and only clear the target if there is one.
+ */
+ if (!clearedReadOnly) {
+ result = HgfsClearReadOnly(to, clearReadOnlyAttr);
+ if (result == 0) {
+ clearedReadOnly = TRUE;
+ LOG(4, ("removed read-only, retrying delete\n"));
+ goto retry;
+ }
+ LOG(4, ("failed to remove read-only attribute\n"));
+ } else {
+ (void)HgfsRestoreReadOnly(to, clearReadOnlyAttr);
+ LOG(4, ("second attempt failed\n"));
+ }
+ break;
+ default:
+ LOG(4, ("failed with result %d\n", result));
+ }
+ break;
+ default:
+ LOG(4, ("Send returned error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ LOG(6, ("Exit(%d)\n", result));
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPackSetattrRequest --
+ *
+ * Setup the Setattr request, depending on the op version.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * On success, the changed argument is set indicating whether the
+ * attributes have actually changed.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsPackSetattrRequest(const char *path, // IN: path to file
+ HgfsAttrInfo *attr, // IN: attributes to set
+ HgfsOp opUsed, // IN: Op to be used
+ HgfsReq *req) // IN/OUT: req packet
+{
+ HgfsAttrV2 *attrV2;
+ HgfsAttr *attrV1;
+ HgfsAttrHint *hints;
+ HgfsAttrChanges *update;
+ char *fileName = NULL;
+ uint32 *fileNameLength = NULL;
+ size_t reqBufferSize;
+ size_t reqSize;
+ int result = 0;
+ ASSERT(req);
+
+ switch (opUsed) {
+ case HGFS_OP_SETATTR_V3: {
+ HgfsRequestSetattrV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ attrV2 = &requestV3->attr;
+ hints = &requestV3->hints;
+
+ /*
+ * Clear attributes, mask, and hints before touching them.
+ * We can't rely on GetNewRequest() to zero our structures, so
+ * make sure to zero them all here.
+ */
+ memset(attrV2, 0, sizeof *attrV2);
+ memset(hints, 0, sizeof *hints);
+
+ /*
+ * When possible, issue a setattr using an existing handle. This will
+ * give us slightly better performance on a Windows server, and is more
+ * correct regardless. If we don't find a handle, fall back on setattr
+ * by name.
+ *
+ * Changing the size (via truncate) requires write permissions. Changing
+ * the times also requires write permissions on Windows, so we require it
+ * here too. Otherwise, any handle will do.
+ */
+ fileName = requestV3->fileName.name;
+ fileNameLength = &requestV3->fileName.length;
+ requestV3->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+ requestV3->fileName.fid = HGFS_INVALID_HANDLE;
+ requestV3->fileName.flags = 0;
+ requestV3->reserved = 0;
+ reqSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+ reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_LARGE_PACKET_MAX, reqSize);
+
+ attrV2->mask = attr->mask;
+ if (attr->mask & (HGFS_ATTR_VALID_SPECIAL_PERMS |
+ HGFS_ATTR_VALID_OWNER_PERMS |
+ HGFS_ATTR_VALID_GROUP_PERMS |
+ HGFS_ATTR_VALID_OTHER_PERMS)) {
+ attrV2->specialPerms = attr->specialPerms;
+ attrV2->ownerPerms = attr->ownerPerms;
+ attrV2->groupPerms = attr->groupPerms;
+ attrV2->otherPerms = attr->otherPerms;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_USERID) {
+ attrV2->userId = attr->userId;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_GROUPID) {
+ attrV2->groupId = attr->groupId;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_SIZE) {
+ attrV2->size = attr->size;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_ACCESS_TIME) {
+ attrV2->accessTime = attr->accessTime;
+ *hints |= HGFS_ATTR_HINT_SET_ACCESS_TIME;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_WRITE_TIME) {
+ attrV2->writeTime = attr->writeTime;
+ *hints |= HGFS_ATTR_HINT_SET_WRITE_TIME;
+ }
+
+ break;
+ }
+ case HGFS_OP_SETATTR_V2: {
+ HgfsRequestSetattrV2 *requestV2;
+
+ requestV2 = (HgfsRequestSetattrV2 *)(HGFS_REQ_PAYLOAD(req));
+
+ attrV2 = &requestV2->attr;
+ hints = &requestV2->hints;
+
+ /*
+ * Clear attributes, mask, and hints before touching them.
+ * We can't rely on GetNewRequest() to zero our structures, so
+ * make sure to zero them all here.
+ */
+ memset(attrV2, 0, sizeof *attrV2);
+ memset(hints, 0, sizeof *hints);
+
+ fileName = requestV2->fileName.name;
+ fileNameLength = &requestV2->fileName.length;
+
+ reqSize = sizeof *requestV2;
+ reqBufferSize = HGFS_NAME_BUFFER_SIZE(HGFS_LARGE_PACKET_MAX, requestV2);
+
+ if (attr->mask & (HGFS_ATTR_VALID_SPECIAL_PERMS |
+ HGFS_ATTR_VALID_OWNER_PERMS |
+ HGFS_ATTR_VALID_GROUP_PERMS |
+ HGFS_ATTR_VALID_OTHER_PERMS)) {
+ attrV2->specialPerms = attr->specialPerms;
+ attrV2->ownerPerms = attr->ownerPerms;
+ attrV2->groupPerms = attr->groupPerms;
+ attrV2->otherPerms = attr->otherPerms;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_USERID) {
+ attrV2->userId = attr->userId;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_GROUPID) {
+ attrV2->groupId = attr->groupId;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_SIZE) {
+ attrV2->size = attr->size;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_ACCESS_TIME) {
+ attrV2->accessTime = attr->accessTime;
+ *hints |= HGFS_ATTR_HINT_SET_ACCESS_TIME;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_WRITE_TIME) {
+ attrV2->writeTime = attr->writeTime;
+ *hints |= HGFS_ATTR_HINT_SET_WRITE_TIME;
+ }
+
+ break;
+ }
+ case HGFS_OP_SETATTR: {
+ HgfsRequestSetattr *request;
+
+ request = (HgfsRequestSetattr *)(HGFS_REQ_PAYLOAD(req));
+
+ attrV1 = &request->attr;
+ update = &request->update;
+
+ /* We'll use these later. */
+ fileName = request->fileName.name;
+ fileNameLength = &request->fileName.length;
+ reqSize = sizeof *request;
+ reqBufferSize = HGFS_NAME_BUFFER_SIZE(HGFS_LARGE_PACKET_MAX, request);
+
+ /*
+ * Clear attributes before touching them.
+ * We can't rely on GetNewRequest() to zero our structures, so
+ * make sure to zero them all here.
+ */
+ memset(attrV1, 0, sizeof *attrV1);
+ memset(update, 0, sizeof *update);
+
+ if (attr->mask & (HGFS_ATTR_VALID_SPECIAL_PERMS |
+ HGFS_ATTR_VALID_OWNER_PERMS |
+ HGFS_ATTR_VALID_GROUP_PERMS |
+ HGFS_ATTR_VALID_OTHER_PERMS)) {
+ *update |= HGFS_ATTR_PERMISSIONS;
+ attrV1->permissions = attr->effectivePerms;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_SIZE) {
+ *update |= HGFS_ATTR_SIZE;
+ attrV1->size = attr->size;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_ACCESS_TIME) {
+ *update |= HGFS_ATTR_ACCESS_TIME |
+ HGFS_ATTR_ACCESS_TIME_SET;
+ attrV1->accessTime = attr->accessTime;
+ }
+ if (attr->mask & HGFS_ATTR_VALID_WRITE_TIME) {
+ *update |= HGFS_ATTR_WRITE_TIME |
+ HGFS_ATTR_WRITE_TIME_SET ;
+ attrV1->writeTime = attr->writeTime;
+ }
+
+ break;
+ }
+ default:
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ return -EPROTO;
+ }
+
+ result = CPName_ConvertTo(path,
+ reqBufferSize,
+ fileName);
+ if (result < 0) {
+ LOG(4, ("CP conversion failed.\n"));
+ return -EINVAL;
+ }
+
+ *fileNameLength = result;
+ req->payloadSize = reqSize + result;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ LOG(6, ("Exit(0)\n"));
+ return 0;
+}
+
+
+/*
+ * Public function implementations.
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsSetattr --
+ *
+ * Handle a setattr request.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsSetattr(const char* path, //IN: Path to file
+ HgfsAttrInfo *attr) //IN: Attribute to set
+{
+ HgfsReq *req;
+ HgfsStatus replyStatus;
+ int result = 0;
+ HgfsOp opUsed;
+
+ LOG(4, ("Entry(%s)\n", path));
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ result = -ENOMEM;
+ LOG(4, ("Error: out of memory -> %d\n", result));
+ goto out;
+ }
+
+retry:
+ /* Fill out the request packet. */
+ opUsed = hgfsVersionSetattr;
+ result = HgfsPackSetattrRequest(path, attr, opUsed, req);
+
+ /* Send the request and process the reply. */
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ /* Get the reply. */
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ switch (result) {
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_SETATTR_V3) {
+ LOG(4, ("Error: reply EPROTO: Version 3 -> version 2.\n"));
+ hgfsVersionSetattr = HGFS_OP_SETATTR_V2;
+ goto retry;
+ } else if (opUsed == HGFS_OP_SETATTR_V2) {
+ LOG(4, ("Error: reply EPROTO: Version 2 -> version 1.\n"));
+ hgfsVersionSetattr = HGFS_OP_SETATTR;
+ goto retry;
+ }
+
+ /* Fallthrough. */
+ default:
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(8, ("Error: EIO: send timed out\n"));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Error: EPROTO: send -> %d\n", result));
+ } else {
+ LOG(4, ("Error: unknown: send -> %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ LOG(6, ("Exit(%d)\n", result));
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsRelease --
+ *
+ * Called when the last user of a file closes it.
+ *
+ * Results:
+ * Returns zero on success, or an error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsRelease(HgfsHandle handle) //IN:File handle to close
+{
+ HgfsReq *req;
+ HgfsOp opUsed;
+ HgfsStatus replyStatus;
+ int result = 0;
+
+ LOG(6, ("Entry(handle = %u)\n", handle));
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+retry:
+ opUsed = hgfsVersionClose;
+ if (opUsed == HGFS_OP_CLOSE_V3) {
+ HgfsRequestCloseV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ requestV3->file = handle;
+ requestV3->reserved = 0;
+ req->payloadSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+
+ } else {
+ HgfsRequestClose *request;
+
+ request = (HgfsRequestClose *)(HGFS_REQ_PAYLOAD(req));
+ request->file = handle;
+ req->payloadSize = sizeof *request;
+ }
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ /* Send the request and process the reply. */
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ /* Get the reply. */
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ switch (result) {
+ case 0:
+ LOG(4, ("Released handle %u\n", handle));
+ break;
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_CLOSE_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 1.\n"));
+ hgfsVersionClose = HGFS_OP_CLOSE;
+ goto retry;
+ }
+ break;
+ default:
+ LOG(4, ("Failed. handle = %u\n", handle));
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(4, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ LOG(6, ("Exit(%d)\n", result));
+ return result;
+}
diff --git a/open-vm-tools/vmhgfs-fuse/file.h b/open-vm-tools/vmhgfs-fuse/file.h
new file mode 100644
index 00000000..12b49da6
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/file.h
@@ -0,0 +1,45 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * file.h --
+ *
+ * High-level filesystem operations for the filesystem portion of
+ * the vmhgfs driver.
+ */
+
+#ifndef _HGFS_DRIVER_FILE_H_
+#define _HGFS_DRIVER_FILE_H_
+
+#define HGFS_FILE_OPEN_PERMS (HGFS_OPEN_VALID_SPECIAL_PERMS | \
+ HGFS_OPEN_VALID_OWNER_PERMS | \
+ HGFS_OPEN_VALID_GROUP_PERMS | \
+ HGFS_OPEN_VALID_OTHER_PERMS)
+
+#define HGFS_FILE_OPEN_MASK (HGFS_OPEN_VALID_MODE | \
+ HGFS_OPEN_VALID_FLAGS | \
+ HGFS_OPEN_VALID_FILE_NAME | \
+ HGFS_OPEN_VALID_SERVER_LOCK)
+
+#define HGFS_FILE_CREATE_MASK (HGFS_FILE_OPEN_MASK | \
+ HGFS_FILE_OPEN_PERMS)
+
+/* Public functions (with respect to the entire module). */
+int HgfsRelease(HgfsHandle handle);
+
+#endif // _HGFS_DRIVER_FILE_H_
diff --git a/open-vm-tools/vmhgfs-fuse/filesystem.c b/open-vm-tools/vmhgfs-fuse/filesystem.c
new file mode 100644
index 00000000..fb9d547d
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/filesystem.c
@@ -0,0 +1,290 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * filesystem.c --
+ *
+ * High-level filesystem operations for the filesystem portion of
+ * the vmhgfs driver.
+ */
+
+#include "filesystem.h"
+#include "transport.h"
+#include "hgfsProto.h"
+#include "hgfsUtil.h"
+#include "module.h"
+#include "request.h"
+#include "fsutil.h"
+#include "vm_assert.h"
+#include "vm_basic_types.h"
+#include "rpcout.h"
+#include "hgfs.h"
+
+
+
+/* Synchronization primitives. */
+pthread_mutex_t hgfsBigLock;
+
+
+/* Global protocol version switch. */
+HgfsOp hgfsVersionCreateSession;
+HgfsOp hgfsVersionDestroySession;
+HgfsOp hgfsVersionOpen;
+HgfsOp hgfsVersionRead;
+HgfsOp hgfsVersionWrite;
+HgfsOp hgfsVersionClose;
+HgfsOp hgfsVersionSearchOpen;
+HgfsOp hgfsVersionSearchRead;
+HgfsOp hgfsVersionSearchClose;
+HgfsOp hgfsVersionGetattr;
+HgfsOp hgfsVersionSetattr;
+HgfsOp hgfsVersionCreateDir;
+HgfsOp hgfsVersionDeleteFile;
+HgfsOp hgfsVersionDeleteDir;
+HgfsOp hgfsVersionRename;
+HgfsOp hgfsVersionQueryVolumeInfo;
+HgfsOp hgfsVersionCreateSymlink;
+
+HgfsFuseState HFState;
+HgfsFuseState *gState = &HFState;
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsResetOps --
+ *
+ * Reset ops with more than one opcode back to the desired opcode.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsResetOps(void)
+{
+ hgfsVersionCreateSession = HGFS_OP_CREATE_SESSION_V4;
+ hgfsVersionDestroySession = HGFS_OP_DESTROY_SESSION_V4;
+ hgfsVersionOpen = HGFS_OP_OPEN_V3;
+ hgfsVersionRead = HGFS_OP_READ_V3;
+ hgfsVersionWrite = HGFS_OP_WRITE_V3;
+ hgfsVersionClose = HGFS_OP_CLOSE_V3;
+ hgfsVersionSearchOpen = HGFS_OP_SEARCH_OPEN_V3;
+ hgfsVersionSearchRead = HGFS_OP_SEARCH_READ_V3;
+ hgfsVersionSearchClose = HGFS_OP_SEARCH_CLOSE_V3;
+ hgfsVersionGetattr = HGFS_OP_GETATTR_V3;
+ hgfsVersionSetattr = HGFS_OP_SETATTR_V3;
+ hgfsVersionCreateDir = HGFS_OP_CREATE_DIR_V3;
+ hgfsVersionDeleteFile = HGFS_OP_DELETE_FILE_V3;
+ hgfsVersionDeleteDir = HGFS_OP_DELETE_DIR_V3;
+ hgfsVersionRename = HGFS_OP_RENAME_V3;
+ hgfsVersionQueryVolumeInfo = HGFS_OP_QUERY_VOLUME_INFO_V3;
+ hgfsVersionCreateSymlink = HGFS_OP_CREATE_SYMLINK_V3;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPackQueryVolumeRequest --
+ *
+ * Setup the query volume request, depending on the op version.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsPackQueryVolumeRequest(const char *path, // IN: File pointer for this open
+ HgfsOp opUsed, // IN: Op to be used.
+ HgfsReq *req) // IN/OUT: Packet to write into
+{
+ char *name;
+ uint32 *nameLength;
+ size_t requestSize;
+ int result;
+
+ ASSERT(req);
+
+ switch (opUsed) {
+ case HGFS_OP_QUERY_VOLUME_INFO_V3: {
+ HgfsRequestQueryVolumeV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ /* We'll use these later. */
+ name = requestV3->fileName.name;
+ nameLength = &requestV3->fileName.length;
+ requestV3->fileName.flags = 0;
+ requestV3->fileName.fid = HGFS_INVALID_HANDLE;
+ requestV3->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+ requestV3->reserved = 0;
+ requestSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+ break;
+ }
+ case HGFS_OP_QUERY_VOLUME_INFO: {
+ HgfsRequestQueryVolume *request;
+
+ request = (HgfsRequestQueryVolume *)(HGFS_REQ_PAYLOAD(req));
+
+ /* We'll use these later. */
+ name = request->fileName.name;
+ nameLength = &request->fileName.length;
+ requestSize = sizeof *request;
+ break;
+ }
+ default:
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ return -EPROTO;
+ }
+
+ /* Convert to CP name. */
+ result = CPName_ConvertTo(path,
+ HGFS_LARGE_PACKET_MAX - (requestSize - 1),
+ name);
+ if (result < 0) {
+ LOG(4, ("CP conversion failed.\n"));
+ return -EINVAL;
+ }
+
+ *nameLength = (uint32) result;
+ req->payloadSize = requestSize + result;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsStatfs --
+ *
+ * Hgfs 'statfs' method. Called when statfs(2) is invoked on the
+ * filesystem.
+ *
+ * Results:
+ * 0 on success
+ * error < 0 on failure
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsStatfs(const char* path, // IN : Path to the file
+ struct statvfs *stat) // OUT: Stat to fill in
+{
+ HgfsReq *req;
+ int result = 0;
+ HgfsOp opUsed;
+ HgfsStatus replyStatus;
+ uint64 freeBytes;
+ uint64 totalBytes;
+
+ LOG(6, ("Entered.\n"));
+ memset(stat, 0, sizeof *stat);
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request.\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+ retry:
+ opUsed = hgfsVersionQueryVolumeInfo;
+ result = HgfsPackQueryVolumeRequest(path, opUsed, req);
+ if (result != 0) {
+ LOG(4, ("Error packing request.\n"));
+ goto out;
+ }
+
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ LOG(6, ("Got reply.\n"));
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ /*
+ * If the statfs succeeded on the server, copy the stats
+ * into the statvfs struct, otherwise return an error.
+ */
+ switch (result) {
+ case 0:
+ stat->f_bsize = HGFS_BLOCKSIZE;
+ if (opUsed == HGFS_OP_QUERY_VOLUME_INFO_V3) {
+ HgfsReplyQueryVolumeV3 * replyV3 = HgfsGetReplyPayload(req);
+
+ totalBytes = replyV3->totalBytes;
+ freeBytes = replyV3->freeBytes;
+
+ } else {
+ totalBytes = ((HgfsReplyQueryVolume *)HGFS_REQ_PAYLOAD(req))->totalBytes;
+ freeBytes = ((HgfsReplyQueryVolume *)HGFS_REQ_PAYLOAD(req))->freeBytes;
+ }
+ stat->f_blocks = (totalBytes + HGFS_BLOCKSIZE - 1) / HGFS_BLOCKSIZE;
+ stat->f_bfree = (freeBytes + HGFS_BLOCKSIZE - 1) / HGFS_BLOCKSIZE;
+ stat->f_bavail = stat->f_bfree;
+ break;
+
+ case -EPERM:
+ /*
+ * We're cheating! This will cause statfs will return success.
+ * We're doing this because an old server will complain when it gets
+ * a statfs on a per-share mount. Rather than have 'df' spit an
+ * error, let's just return all zeroes.
+ */
+ result = 0;
+ break;
+
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_QUERY_VOLUME_INFO_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 1.\n"));
+ hgfsVersionQueryVolumeInfo = HGFS_OP_QUERY_VOLUME_INFO;
+ goto retry;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(4, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ return result;
+}
diff --git a/open-vm-tools/vmhgfs-fuse/filesystem.h b/open-vm-tools/vmhgfs-fuse/filesystem.h
new file mode 100644
index 00000000..97fdc507
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/filesystem.h
@@ -0,0 +1,49 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * filesystem.h --
+ *
+ * High-level filesystem operations for the filesystem portion of
+ * the vmhgfs driver.
+ */
+
+#ifndef _HGFS_DRIVER_FILESYSTEM_H_
+#define _HGFS_DRIVER_FILESYSTEM_H_
+
+#include "vm_basic_types.h"
+#include <sys/statvfs.h>
+
+typedef struct HgfsFuseState {
+ Bool sessionEnabled;
+ uint64 sessionId;
+ uint8 headerVersion;
+ /*
+ * When mount a subdirectory of hgfs shared directory, basePath holds
+ * the prefix to the root. e.g. 'mount.vmhgfs .host:/shared/sub /hgfs',
+ * base path would be '/shared/sub' (trailing '/' will be removed).
+ */
+ char *basePath;
+ size_t basePathLen;
+
+} HgfsFuseState;
+
+/* Public functions (with respect to the entire module). */
+int HgfsStatfs(const char *path, struct statvfs *stat);
+
+#endif // _HGFS_DRIVER_FILESYSTEM_H_
diff --git a/open-vm-tools/vmhgfs-fuse/fsutil.c b/open-vm-tools/vmhgfs-fuse/fsutil.c
new file mode 100644
index 00000000..042c223c
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/fsutil.c
@@ -0,0 +1,784 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * fsutil.c --
+ *
+ * Functions used in more than one type of filesystem operation will be
+ * exported from this file.
+ */
+
+#include <limits.h>
+#include "module.h"
+#include "cache.h"
+
+typedef unsigned short umode_t;
+
+
+static int
+HgfsPackGetattrRequest(HgfsReq *req,
+ HgfsHandle handle,
+ const char* path,
+ Bool allowHandleReuse,
+ HgfsOp opUsed,
+ HgfsAttrInfo *attr);
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsUnpackGetattrReply --
+ *
+ * This function abstracts the differences between a GetattrV1 and
+ * a GetattrV2. The caller provides the packet containing the reply
+ * and we populate the AttrInfo with version-independent information.
+ *
+ * Note that attr->requestType has already been populated so that we
+ * know whether to expect a V1 or V2 reply.
+ *
+ * Results:
+ * 0 on success, anything else on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsUnpackGetattrReply(HgfsReq *req, // IN: Reply packet
+ HgfsAttrInfo *attr) // IN/OUT: Attributes
+{
+ int result;
+ char *name = NULL;
+ uint32 length = 0;
+ void *rawAttr;
+ HgfsOp opUsed;
+
+ ASSERT(req);
+ ASSERT(attr);
+
+ opUsed = attr->requestType;
+ switch (opUsed) {
+ case HGFS_OP_GETATTR_V3: {
+ HgfsReplyGetattrV3 *getattrReplyV3 = HgfsGetReplyPayload(req);
+
+ rawAttr = &getattrReplyV3->attr;
+ break;
+ }
+ case HGFS_OP_GETATTR_V2: {
+ HgfsReplyGetattrV2 *getattrReplyV2 =
+ (HgfsReplyGetattrV2 *)(HGFS_REQ_PAYLOAD(req));
+
+ rawAttr = &getattrReplyV2->attr;
+ break;
+ }
+ case HGFS_OP_GETATTR: {
+ HgfsReplyGetattr *getattrReplyV1;
+ getattrReplyV1 = (HgfsReplyGetattr *)(HGFS_REQ_PAYLOAD(req));
+ rawAttr = &getattrReplyV1->attr;
+ break;
+ }
+ default:
+ LOG(4, ("Unexpected op in reply packet. opUsed = %d\n", opUsed));
+ return -EPROTO;
+ }
+
+ result = HgfsUnpackCommonAttr(rawAttr, opUsed, attr);
+ if (result != 0) {
+ return result;
+ }
+
+ /* GetattrV2+ also wants a symlink target if it exists. */
+ if (attr->requestType == HGFS_OP_GETATTR_V3) {
+ HgfsReplyGetattrV3 *replyV3 = HgfsGetReplyPayload(req);
+
+ name = replyV3->symlinkTarget.name;
+ length = replyV3->symlinkTarget.length;
+
+ /* Skip the symlinkTarget if it's too long. */
+ if (length > HGFS_NAME_BUFFER_SIZET(HGFS_LARGE_PACKET_MAX,
+ sizeof *replyV3 + sizeof (HgfsReply))) {
+ LOG(4, ("symlink target name too long, ignoring\n"));
+ return -ENAMETOOLONG;
+ }
+ } else if (attr->requestType == HGFS_OP_GETATTR_V2) {
+ HgfsReplyGetattrV2 *replyV2 = (HgfsReplyGetattrV2 *)
+ (HGFS_REQ_PAYLOAD(req));
+ name = replyV2->symlinkTarget.name;
+ length = replyV2->symlinkTarget.length;
+
+ /* Skip the symlinkTarget if it's too long. */
+ if (length > HGFS_NAME_BUFFER_SIZE(HGFS_LARGE_PACKET_MAX, replyV2)) {
+ LOG(4, ("symlink target name too long, ignoring\n"));
+ return -ENAMETOOLONG;
+ }
+ }
+
+ if (length != 0) {
+ attr->fileName = (char*)malloc(length + 1);
+ if (attr->fileName == NULL) {
+ LOG(4, ("Out of memory allocating symlink target name, ignoring\n"));
+ return -ENOMEM;
+ }
+
+ /* Copy and convert. From now on, the symlink target is in UTF8. */
+ memcpy(attr->fileName, name, length);
+ CPNameLite_ConvertFrom(attr->fileName, length, '/');
+ attr->fileName[length] = '\0';
+ }
+
+ /*
+ * Set the access mode. For hosts that don't give us group or other
+ * bits (Windows), we use the owner bits in their stead.
+ */
+ ASSERT(attr->mask & HGFS_ATTR_VALID_OWNER_PERMS);
+ if ((attr->mask & HGFS_ATTR_VALID_GROUP_PERMS) == 0) {
+ attr->groupPerms = attr->ownerPerms;
+ attr->mask |= HGFS_ATTR_VALID_GROUP_PERMS;
+ }
+ if ((attr->mask & HGFS_ATTR_VALID_OTHER_PERMS) == 0) {
+ attr->otherPerms = attr->ownerPerms;
+ attr->mask |= HGFS_ATTR_VALID_OTHER_PERMS;
+ }
+
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPackGetattrRequest --
+ *
+ * Setup the getattr request
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer
+ HgfsHandle handle, // IN: file handle
+ const char* path, // IN: path to a file
+ Bool handleReuse, // IN: Can we use a handle?
+ HgfsOp opUsed, // IN: Op to be used
+ HgfsAttrInfo *attr) // OUT: Attrs to update
+{
+ size_t reqBufferSize;
+ size_t reqSize;
+ int result = 0;
+ char *fileName = NULL;
+ uint32 *fileNameLength = NULL;
+ ASSERT(attr);
+ ASSERT(req);
+ ASSERT(path);
+ attr->requestType = opUsed;
+ (void) handle;
+ (void) handleReuse;
+
+ switch (opUsed) {
+ case HGFS_OP_GETATTR_V3: {
+ HgfsRequestGetattrV3 *requestV3 = HgfsGetRequestPayload(req);
+
+ /* Fill out the request packet. */
+ requestV3->hints = 0;
+ fileName = requestV3->fileName.name;
+ fileNameLength = &requestV3->fileName.length;
+ requestV3->fileName.flags = 0;
+ requestV3->fileName.fid = HGFS_INVALID_HANDLE;
+ requestV3->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+
+ requestV3->reserved = 0;
+ reqSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+ reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_LARGE_PACKET_MAX, reqSize);
+ break;
+ }
+
+ case HGFS_OP_GETATTR_V2: {
+ HgfsRequestGetattrV2 *requestV2;
+
+ LOG(8, ("Version 2 OP type encountered\n"));
+
+ requestV2 = (HgfsRequestGetattrV2 *)(HGFS_REQ_PAYLOAD(req));
+ requestV2->hints = 0;
+ fileName = requestV2->fileName.name;
+ fileNameLength = &requestV2->fileName.length;
+ reqSize = sizeof *requestV2;
+ reqBufferSize = HGFS_NAME_BUFFER_SIZE(HGFS_LARGE_PACKET_MAX, requestV2);
+ break;
+ }
+
+ case HGFS_OP_GETATTR: {
+ HgfsRequestGetattr *requestV1;
+ requestV1 = (HgfsRequestGetattr *)(HGFS_REQ_PAYLOAD(req));
+ fileName = requestV1->fileName.name;
+ fileNameLength = &requestV1->fileName.length;
+ reqSize = sizeof *requestV1;
+ reqBufferSize = HGFS_NAME_BUFFER_SIZE(HGFS_LARGE_PACKET_MAX, requestV1);
+ break;
+ }
+
+ default:
+ LOG(8, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ result = -EPROTO;
+ goto out;
+ }
+
+ if (fileName != NULL) {
+ /* Convert to CP name. */
+ result = CPName_ConvertTo(path,
+ reqBufferSize,
+ fileName);
+ LOG(8, ("Converted path %s\n", fileName));
+ if (result < 0) {
+ LOG(8, ("CP conversion failed.\n"));
+ result = -EINVAL;
+ goto out;
+ }
+ *fileNameLength = result;
+ }
+
+ req->payloadSize = reqSize + result;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ result = 0;
+
+out:
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsUnpackCommonAttr --
+ *
+ * This function abstracts the HgfsAttr struct behind HgfsAttrInfo.
+ *
+ * Results:
+ * Zero on success, non-zero otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+int
+HgfsUnpackCommonAttr(void *rawAttr, // IN: Attr in reply packet
+ HgfsOp requestType, // IN: request type
+ HgfsAttrInfo *attrInfo) // OUT: Attributes
+{
+ HgfsAttrV2 *attrV2 = NULL;
+ HgfsAttr *attrV1 = NULL;
+
+ ASSERT(rawAttr);
+ ASSERT(attrInfo);
+
+ switch (requestType) {
+ case HGFS_OP_GETATTR_V3:
+ attrV2 = rawAttr;
+ break;
+ case HGFS_OP_GETATTR_V2:
+ attrV2 = rawAttr;
+ break;
+ case HGFS_OP_GETATTR:
+ attrV1 = rawAttr;
+ break;
+ case HGFS_OP_SEARCH_READ_V3:
+ attrV2 = rawAttr;
+ break;
+ case HGFS_OP_SEARCH_READ_V2:
+ attrV2 = rawAttr;
+ break;
+ case HGFS_OP_SEARCH_READ:
+ attrV1 = rawAttr;
+ break;
+ default:
+ LOG(4, ("Unexpected op in reply packet: requestType = %d\n", requestType));
+ return -EPROTO;
+ }
+
+ attrInfo->requestType = requestType;
+ if (attrV2 != NULL) {
+ attrInfo->mask = 0;
+
+ if (attrV2->mask & HGFS_ATTR_VALID_TYPE) {
+ attrInfo->type = attrV2->type;
+ attrInfo->mask |= HGFS_ATTR_VALID_TYPE;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_SIZE) {
+ attrInfo->size = attrV2->size;
+ attrInfo->mask |= HGFS_ATTR_VALID_SIZE;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_ACCESS_TIME) {
+ attrInfo->accessTime = attrV2->accessTime;
+ attrInfo->mask |= HGFS_ATTR_VALID_ACCESS_TIME;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_WRITE_TIME) {
+ attrInfo->writeTime = attrV2->writeTime;
+ attrInfo->mask |= HGFS_ATTR_VALID_WRITE_TIME;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_CHANGE_TIME) {
+ attrInfo->attrChangeTime = attrV2->attrChangeTime;
+ attrInfo->mask |= HGFS_ATTR_VALID_CHANGE_TIME;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_SPECIAL_PERMS) {
+ attrInfo->specialPerms = attrV2->specialPerms;
+ attrInfo->mask |= HGFS_ATTR_VALID_SPECIAL_PERMS;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_OWNER_PERMS) {
+ attrInfo->ownerPerms = attrV2->ownerPerms;
+ attrInfo->mask |= HGFS_ATTR_VALID_OWNER_PERMS;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_GROUP_PERMS) {
+ attrInfo->groupPerms = attrV2->groupPerms;
+ attrInfo->mask |= HGFS_ATTR_VALID_GROUP_PERMS;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_OTHER_PERMS) {
+ attrInfo->otherPerms = attrV2->otherPerms;
+ attrInfo->mask |= HGFS_ATTR_VALID_OTHER_PERMS;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_USERID) {
+ attrInfo->userId = attrV2->userId;
+ attrInfo->mask |= HGFS_ATTR_VALID_USERID;
+ }
+ if (attrV2->mask & HGFS_ATTR_VALID_GROUPID) {
+ attrInfo->groupId = attrV2->groupId;
+ attrInfo->mask |= HGFS_ATTR_VALID_GROUPID;
+ }
+
+ if (attrV2->mask & HGFS_ATTR_VALID_FILEID) {
+ attrInfo->hostFileId = attrV2->hostFileId;
+ attrInfo->mask |= HGFS_ATTR_VALID_FILEID;
+ }
+ /* Windows Host */
+ if (attrV2->mask & HGFS_ATTR_VALID_NON_STATIC_FILEID) {
+ attrInfo->hostFileId = attrV2->hostFileId;
+ attrInfo->mask |= HGFS_ATTR_VALID_NON_STATIC_FILEID;
+ }
+
+ if (attrV2->mask & HGFS_ATTR_VALID_EFFECTIVE_PERMS) {
+ attrInfo->effectivePerms = attrV2->effectivePerms;
+ attrInfo->mask |= HGFS_ATTR_VALID_EFFECTIVE_PERMS;
+ }
+ } else if (attrV1 != NULL) {
+ /* Implicit mask for a Version 1 attr. */
+ attrInfo->mask = HGFS_ATTR_VALID_TYPE |
+ HGFS_ATTR_VALID_SIZE |
+ HGFS_ATTR_VALID_ACCESS_TIME |
+ HGFS_ATTR_VALID_WRITE_TIME |
+ HGFS_ATTR_VALID_CHANGE_TIME |
+ HGFS_ATTR_VALID_OWNER_PERMS |
+ HGFS_ATTR_VALID_EFFECTIVE_PERMS;
+
+ attrInfo->type = attrV1->type;
+ attrInfo->size = attrV1->size;
+ attrInfo->accessTime = attrV1->accessTime;
+ attrInfo->writeTime = attrV1->writeTime;
+ attrInfo->attrChangeTime = attrV1->attrChangeTime;
+ attrInfo->ownerPerms = attrV1->permissions;
+ attrInfo->effectivePerms = attrV1->permissions;
+ }
+
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPrivateGetattr --
+ *
+ * Internal getattr routine. Send a getattr request to the server
+ * for the indicated remote name, and if it succeeds copy the
+ * results of the getattr into the provided HgfsAttrInfo.
+ *
+ * attr->fileName will be allocated on success if the file is a
+ * symlink; it's the caller's duty to free it.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsPrivateGetattr(HgfsHandle handle, // IN: file handle
+ const char* path, // IN: path
+ HgfsAttrInfo *attr) // OUT: Attr to copy into
+{
+ HgfsReq *req;
+ HgfsStatus replyStatus;
+ HgfsOp opUsed;
+ int result = 0;
+ Bool allowHandleReuse = TRUE;
+
+ ASSERT(attr);
+ LOG( 4,("path = %s, handle = %u\n", path, handle));
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(8, ("Out of memory while getting new request\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+retry:
+ opUsed = hgfsVersionGetattr;
+ LOG(4, ("Before HgfsPackGetattrRequest\n"));
+ result = HgfsPackGetattrRequest(req, handle,
+ path, allowHandleReuse, opUsed, attr);
+
+ LOG(4, ("Before Send, Path = %s result = %d \n", path, result));
+
+ if (result != 0) {
+ LOG(8, ("No attrs.\n"));
+ goto out;
+ }
+
+ result = HgfsSendRequest(req);
+
+ LOG( 4,("After Send, path = %s result = %d \n", path, result));
+
+ if (result == 0) {
+ LOG(8, ("Got reply\n"));
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+
+ /*
+ * If the getattr succeeded on the server, copy the stats
+ * into the HgfsAttrInfo, otherwise return an error.
+ */
+ switch (result) {
+ case 0:
+ result = HgfsUnpackGetattrReply(req, attr);
+ break;
+
+ case -EBADF:
+ /*
+ * There's no reason why the server should have sent us this error
+ * when we haven't used a handle. But to prevent an infinite loop in
+ * the driver, let's make sure that we don't retry again.
+ */
+ break;
+
+ case -EPROTO:
+ /* Retry with older version(s). Set globally. */
+ if (attr->requestType == HGFS_OP_GETATTR_V3) {
+ LOG(8, ("Version 3 not supported. Falling back to version 2.\n"));
+ hgfsVersionGetattr = HGFS_OP_GETATTR_V2;
+ goto retry;
+ } else if (attr->requestType == HGFS_OP_GETATTR_V2) {
+ LOG(8, ("Version 2 not supported. Falling back to version 1.\n"));
+ hgfsVersionGetattr = HGFS_OP_GETATTR;
+ goto retry;
+ }
+
+ /* Fallthrough. */
+ default:
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(8, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(8, ("Server returned error: %d\n", result));
+ } else {
+ LOG(8, ("Unknown error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetOpenMode --
+ *
+ * Based on the flags requested by the process making the open()
+ * syscall, determine which open mode (access type) to request from
+ * the server.
+ *
+ * Results:
+ * Returns the correct HgfsOpenMode enumeration to send to the
+ * server, or -1 on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsGetOpenMode(uint32 flags) // IN: Open flags
+{
+ uint32 mask = O_RDONLY|O_WRONLY|O_RDWR;
+ int result = -1;
+
+ LOG(6, ("entered\n"));
+
+ /*
+ * Mask the flags to only look at the access type.
+ */
+ flags &= mask;
+
+ /* Pick the correct HgfsOpenMode. */
+ switch (flags) {
+
+ case O_RDONLY:
+ result = HGFS_OPEN_MODE_READ_ONLY;
+ break;
+
+ case O_WRONLY:
+ result = HGFS_OPEN_MODE_WRITE_ONLY;
+ break;
+
+ case O_RDWR:
+ result = HGFS_OPEN_MODE_READ_WRITE;
+ break;
+
+ default:
+ /*
+ * This should never happen, but it could if a userlevel program
+ * is behaving poorly.
+ */
+ LOG(4, ("invalid open flags %o\n", flags));
+ result = -1;
+ break;
+ }
+
+ return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsStatusConvertToLinux --
+ *
+ * Convert a cross-platform HGFS status code to its Linux-kernel specific
+ * counterpart.
+ *
+ * Rather than encapsulate the status codes within an array indexed by the
+ * various HGFS status codes, we explicitly enumerate them in a switch
+ * statement, saving the reader some time when matching HGFS status codes
+ * against Linux status codes.
+ *
+ * Results:
+ * Zero if the converted status code represents success, negative error
+ * otherwise. Unknown status codes are converted to the more generic
+ * "protocol error" status code to maintain forwards compatibility.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsStatusConvertToLinux(HgfsStatus hgfsStatus) // IN: Status code to convert
+{
+ switch (hgfsStatus) {
+ case HGFS_STATUS_SUCCESS:
+ return 0;
+
+ case HGFS_STATUS_NO_SUCH_FILE_OR_DIR:
+ case HGFS_STATUS_INVALID_NAME:
+ return -ENOENT;
+
+ case HGFS_STATUS_INVALID_HANDLE:
+ return -EBADF;
+
+ case HGFS_STATUS_OPERATION_NOT_PERMITTED:
+ return -EPERM;
+
+ case HGFS_STATUS_FILE_EXISTS:
+ return -EEXIST;
+
+ case HGFS_STATUS_NOT_DIRECTORY:
+ return -ENOTDIR;
+
+ case HGFS_STATUS_DIR_NOT_EMPTY:
+ return -ENOTEMPTY;
+
+ case HGFS_STATUS_PROTOCOL_ERROR:
+ return -EPROTO;
+
+ case HGFS_STATUS_ACCESS_DENIED:
+ case HGFS_STATUS_SHARING_VIOLATION:
+ return -EACCES;
+
+ case HGFS_STATUS_NO_SPACE:
+ return -ENOSPC;
+
+ case HGFS_STATUS_OPERATION_NOT_SUPPORTED:
+ return -EOPNOTSUPP;
+
+ case HGFS_STATUS_NAME_TOO_LONG:
+ return -ENAMETOOLONG;
+
+ case HGFS_STATUS_GENERIC_ERROR:
+ return -EIO;
+
+ default:
+ LOG(10, ("Unknown error: %u\n", hgfsStatus));
+ return -EIO;
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsCalcBlockSize --
+ *
+ * Calculate the number of 512 byte blocks used.
+ *
+ * Round the size to the next whole block and divide by the block size
+ * to get the number of 512 byte blocks.
+ * Note, this is taken from the nfs client and is simply performing:
+ * (size + 512-1)/ 512)
+ *
+ * Results:
+ * The number of 512 byte blocks for the size.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+unsigned long
+HgfsCalcBlockSize(uint64 tsize)
+{
+ loff_t used = (tsize + 511) >> 9;
+ return (used > ULONG_MAX) ? ULONG_MAX : used;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsClearReadOnly --
+ *
+ * Try to remove the file/dir read only attribute.
+ *
+ * Note when running on Windows servers the entry may have the read-only
+ * flag set and prevent a rename or delete operation from occuring.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsClearReadOnly(const char* path, // IN: file/dir to remove read only
+ HgfsAttrInfo *enableWrite) // OUT: attributes
+{
+ int result;
+
+ LOG(4, ("Entry(path = %s)\n", path));
+
+ result = HgfsGetAttrCache(path, enableWrite);
+ LOG(4, ("Retrieve attr from cache. result = %d \n", result));
+ if (result != 0) {
+ result = HgfsPrivateGetattr(HGFS_INVALID_HANDLE,
+ path,
+ enableWrite);
+ }
+
+ if (result != 0) {
+ LOG(4, ("error: attributes for read-only file\n"));
+ goto out;
+ }
+
+ LOG(4, ("%s perms %#o %#o %#o\n", path, enableWrite->ownerPerms,
+ enableWrite->groupPerms, enableWrite->otherPerms));
+
+ /*
+ * Use only the permissions bits and add write for the owner.
+ */
+ enableWrite->mask &= (HGFS_ATTR_VALID_SPECIAL_PERMS |
+ HGFS_ATTR_VALID_OWNER_PERMS |
+ HGFS_ATTR_VALID_GROUP_PERMS |
+ HGFS_ATTR_VALID_OTHER_PERMS);
+ enableWrite->ownerPerms |= HGFS_PERM_WRITE;
+
+ result = HgfsSetattr(path, enableWrite);
+
+out:
+ LOG(4, ("Exit(%d)\n", result));
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsRestoreReadOnly --
+ *
+ * Try to restore the file/dir read only attribute.
+ *
+ * Note This is the store for the above clear operation and expects
+ * the attributes to have valid owner permissons at a minimum.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsRestoreReadOnly(const char* path, // IN: file/dir to remove read only
+ HgfsAttrInfo *enableWrite) // IN: attributes
+{
+ int result;
+
+ LOG(4, ("Entry(path = %s)\n", path));
+
+ /*
+ * Clear the write permissions bit for the owner.
+ */
+ ASSERT((enableWrite->mask & HGFS_ATTR_VALID_OWNER_PERMS) != 0);
+
+ enableWrite->ownerPerms &= ~HGFS_PERM_WRITE;
+ result = HgfsSetattr(path, enableWrite);
+ LOG(4, ("Exit(%d)\n", result));
+ return result;
+}
diff --git a/open-vm-tools/vmhgfs-fuse/fsutil.h b/open-vm-tools/vmhgfs-fuse/fsutil.h
new file mode 100644
index 00000000..34b6d489
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/fsutil.h
@@ -0,0 +1,145 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * fsutil.h --
+ *
+ * Functions used in more than one type of filesystem operation will be
+ * exported from this file.
+ */
+
+#ifndef _HGFS_DRIVER_FSUTIL_H_
+#define _HGFS_DRIVER_FSUTIL_H_
+
+
+#include "request.h"
+#include "vm_basic_types.h"
+#include "hgfsProto.h"
+#include <fuse.h>
+
+#if defined(__FreeBSD__) || defined(__SOLARIS__) || defined(__APPLE__)
+typedef long long loff_t;
+#endif
+
+/*
+ * Struct used to pass around attributes.
+ * These aren't just the attributes seen in HgfsAttr[V2]; we add a filename
+ * pointer for convenience (used by SearchRead and Getattr).
+ */
+typedef struct HgfsAttrInfo {
+ HgfsOp requestType;
+ HgfsAttrValid mask;
+ HgfsFileType type; /* File type */
+ uint64 size; /* File size (in bytes) */
+ uint64 accessTime; /* Time of last access */
+ uint64 writeTime; /* Time of last write */
+ uint64 attrChangeTime; /* Time file attributes were last changed */
+ HgfsPermissions specialPerms; /* Special permissions bits */
+ HgfsPermissions ownerPerms; /* Owner permissions bits */
+ HgfsPermissions groupPerms; /* Group permissions bits */
+ HgfsPermissions otherPerms; /* Other permissions bits */
+ HgfsPermissions effectivePerms; /* Permissions in effect for the user on the
+ host. */
+ uint32 userId; /* UID */
+ uint32 groupId; /* GID */
+ uint64 hostFileId; /* Inode number */
+ char *fileName; /* Either symlink target or filename */
+} HgfsAttrInfo;
+
+int
+HgfsClearReadOnly(const char* path,
+ HgfsAttrInfo *enableWrite);
+
+int
+HgfsRestoreReadOnly(const char* path,
+ HgfsAttrInfo *enableWrite);
+
+ssize_t
+HgfsWrite(struct fuse_file_info *fi,
+ const char *buf,
+ size_t count,
+ loff_t offset);
+
+int
+HgfsRename(const char* from, const char* to);
+
+/* HGFS file operations for files. */
+
+int
+HgfsOpen(const char *path,
+ struct fuse_file_info *fi);
+
+int
+HgfsCreate(const char *path,
+ mode_t permsMode,
+ struct fuse_file_info *fi);
+
+ssize_t
+HgfsRead(struct fuse_file_info *fi,
+ char *buf,
+ size_t count,
+ loff_t offset);
+
+int
+HgfsSetattr(const char* path,
+ HgfsAttrInfo *attr);
+
+
+int HgfsUnpackCommonAttr(void *rawAttr,
+ HgfsOp requestType,
+ HgfsAttrInfo *attrInfo);
+
+int
+HgfsPrivateGetattr(HgfsHandle handle,
+ const char* path,
+ HgfsAttrInfo *attr);
+
+int
+HgfsStatusConvertToLinux(HgfsStatus hgfsStatus);
+
+int
+HgfsGetOpenMode(uint32 flags);
+
+
+int
+HgfsDirOpen(const char* path, HgfsHandle* handle);
+
+int
+HgfsReaddir(HgfsHandle handle,
+ void *dirent,
+ fuse_fill_dir_t filldir);
+
+int
+HgfsMkdir(const char *path,
+ int mode);
+
+int
+HgfsDelete(const char* path,
+ HgfsOp op);
+
+int
+HgfsSymlink(const char* source,
+ const char *symname);
+
+void
+HgfsResetOps(void);
+
+unsigned long
+HgfsCalcBlockSize(uint64 tsize);
+
+#endif // _HGFS_DRIVER_FSUTIL_H_
diff --git a/open-vm-tools/vmhgfs-fuse/link.c b/open-vm-tools/vmhgfs-fuse/link.c
new file mode 100644
index 00000000..a00e8446
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/link.c
@@ -0,0 +1,222 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * link.c --
+ *
+ * Symlink-specific operations for HGFS driver
+ */
+
+
+
+#include "module.h"
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPackSymlinkCreateRequest --
+ *
+ * Setup the create symlink request, depending on the op version.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsPackSymlinkCreateRequest(const char* symlink, // IN: path of the link
+ const char *symname, // IN: Target name
+ HgfsOp opUsed, // IN: Op to be used
+ HgfsReq *req) // IN/OUT: Packet to write into
+{
+ HgfsRequestSymlinkCreateV3 *requestV3 = NULL;
+ HgfsRequestSymlinkCreate *request = NULL;
+ char *symlinkName;
+ uint32 *symlinkNameLength;
+ char *targetName;
+ uint32 *targetNameLength;
+ size_t targetNameBytes;
+
+ size_t requestSize;
+ int result;
+
+ switch (opUsed) {
+ case HGFS_OP_CREATE_SYMLINK_V3: {
+ requestV3 = HgfsGetRequestPayload(req);
+
+ /* We'll use these later. */
+ symlinkName = requestV3->symlinkName.name;
+ symlinkNameLength = &requestV3->symlinkName.length;
+ requestV3->symlinkName.flags = 0;
+ requestV3->symlinkName.fid = HGFS_INVALID_HANDLE;
+ requestV3->symlinkName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+ requestV3->reserved = 0;
+ requestSize = sizeof(*requestV3) + HgfsGetRequestHeaderSize();
+ break;
+ }
+ case HGFS_OP_CREATE_SYMLINK: {
+ request = (HgfsRequestSymlinkCreate *)(HGFS_REQ_PAYLOAD(req));
+
+ /* We'll use these later. */
+ symlinkName = request->symlinkName.name;
+ symlinkNameLength = &request->symlinkName.length;
+ requestSize = sizeof *request;
+ break;
+ }
+ default:
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ return -EPROTO;
+ }
+
+
+ /* Convert symlink name to CP format. */
+ result = CPName_ConvertTo(symlink,
+ HGFS_LARGE_PACKET_MAX - (requestSize - 1),
+ symlinkName);
+ if (result < 0) {
+ LOG(4, ("SymlinkName CP conversion failed.\n"));
+ return -EINVAL;
+ }
+
+ *symlinkNameLength = result;
+ req->payloadSize = requestSize + result;
+
+ /*
+ * Note the different buffer length. This is because HgfsRequestSymlink
+ * contains two filenames, and once we place the first into the packet we
+ * must account for it when determining the amount of buffer available for
+ * the second.
+ *
+ * Also note that targetNameBytes accounts for the NUL character. Once
+ * we've converted it to CP name, it won't be NUL-terminated and the length
+ * of the string in the packet itself won't account for it.
+ */
+ if (opUsed == HGFS_OP_CREATE_SYMLINK_V3) {
+ HgfsFileNameV3 *fileNameP;
+ fileNameP = (HgfsFileNameV3 *)((char *)&requestV3->symlinkName +
+ sizeof requestV3->symlinkName + result);
+ targetName = fileNameP->name;
+ targetNameLength = &fileNameP->length;
+ fileNameP->flags = 0;
+ fileNameP->fid = HGFS_INVALID_HANDLE;
+ fileNameP->caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
+ } else {
+ HgfsFileName *fileNameP;
+ fileNameP = (HgfsFileName *)((char *)&request->symlinkName +
+ sizeof request->symlinkName + result);
+ targetName = fileNameP->name;
+ targetNameLength = &fileNameP->length;
+ }
+ targetNameBytes = strlen(symname) + 1;
+
+ /* Copy target name into request packet. */
+ if (targetNameBytes > HGFS_LARGE_PACKET_MAX - (requestSize - 1)) {
+ LOG(4, ("Target name is too long.\n"));
+ return -EINVAL;
+ }
+ memcpy(targetName, symname, targetNameBytes);
+ LOG(6, ("Target name: \"%s\"\n", targetName));
+
+ /* Convert target name to CPName-lite format. */
+ CPNameLite_ConvertTo(targetName, targetNameBytes - 1, '/');
+
+ *targetNameLength = targetNameBytes - 1;
+ req->payloadSize += targetNameBytes - 1;
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsSymlink --
+ *
+ * Handle a symlink request
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsSymlink(const char* source, // IN: Source name
+ const char *symname) // IN: Target name
+{
+ HgfsReq *req;
+ int result = 0;
+ HgfsOp opUsed;
+ HgfsStatus replyStatus;
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request.\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+ retry:
+ opUsed = hgfsVersionCreateSymlink;
+ result = HgfsPackSymlinkCreateRequest(source, symname, opUsed, req);
+ if (result != 0) {
+ LOG(4, ("Error packing request.\n"));
+ goto out;
+ }
+
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ LOG(6, ("Got reply.\n"));
+ replyStatus = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(replyStatus);
+ if (result == 0) {
+ LOG(6, ("Symlink created successfully, instantiating dentry.\n"));
+ } else if (result == -EPROTO) {
+ /* Retry with older version(s). Set globally. */
+ if (opUsed == HGFS_OP_CREATE_SYMLINK_V3) {
+ LOG(4, ("Version 3 not supported. Falling back to version 2.\n"));
+ hgfsVersionCreateSymlink = HGFS_OP_CREATE_SYMLINK;
+ goto retry;
+ } else {
+ LOG(6, ("Symlink was not created, error %d\n", result));
+ }
+ }
+ } else if (result == -EIO) {
+ LOG(4, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+
+ return result;
+}
diff --git a/open-vm-tools/vmhgfs-fuse/linux/list.h b/open-vm-tools/vmhgfs-fuse/linux/list.h
new file mode 100644
index 00000000..ed72509f
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/linux/list.h
@@ -0,0 +1,263 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+#ifndef __LIST_H
+#define __LIST_H
+
+/*
+ * This file is from Linux Kernel (include/linux/list.h)
+ * and modified by simply removing hardware prefetching of list items.
+ * Here by copyright, credits attributed to wherever they belong.
+ * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
+ */
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = (void *) 0;
+ entry->prev = (void *) 0;
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); \
+ pos = pos->next)
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; pos != (head); \
+ pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+
+#endif
diff --git a/open-vm-tools/vmhgfs-fuse/main.c b/open-vm-tools/vmhgfs-fuse/main.c
new file mode 100644
index 00000000..fa745780
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/main.c
@@ -0,0 +1,1378 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * main.c --
+ *
+ * Main entry points for fuse file operations for HGFS
+ */
+
+#if FUSE_USE_VERSION >= 26
+#define HAVE_UTIMENSAT 1
+#endif
+
+#include "module.h"
+#include "cache.h"
+#include "filesystem.h"
+#include "file.h"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * getAbsPath
+ *
+ * This function takes the file path used by the local file system
+ * (which is relative to the HGFS mount) and generates the HGFS absolute
+ * path to send to the HGFS server.
+ * the absolute path will be allocated, which is the HGFS share and
+ * all other intermediate subdirectories that contain the file or folder.
+ *
+ * Results:
+ * zero on success, negative number for error.
+ *
+ * Side effects:
+ * Caller is responsible to free the absolute path if it's different
+ * from the path.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+getAbsPath(const char *path, // IN
+ char **abspath) // OUT
+{
+ size_t size;
+ int res = 0;
+
+ if (gState->basePathLen > 0) {
+ size = gState->basePathLen + strlen(path) + 1;
+ *abspath = (char *)malloc(size);
+ if (*abspath == NULL) {
+ LOG(4, ("Can't allocate memory!\n"));
+ res = -ENOMEM;
+ goto exit;
+ }
+ snprintf(*abspath, size, "%s%s", gState->basePath, path);
+
+ } else {
+ *abspath = (char *)path;
+ }
+
+exit:
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * freeAbsPath
+ *
+ * This function free's the absolute path allocated from getAbsPath
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+freeAbsPath(char *abspath) // IN
+{
+ if (gState->basePathLen > 0) {
+ free(abspath);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_getattr
+ *
+ * Get the attributes from the HGFS server and populate struct stat.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_getattr(const char *path, //IN: path of a file/directory
+ struct stat *stbuf) //IN/OUT: file/directoy attribute
+{
+ HgfsHandle fileHandle = HGFS_INVALID_HANDLE;
+ HgfsAttrInfo newAttr = {0};
+ HgfsAttrInfo *attr = &newAttr;
+ uint32 d_type;
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s)\n", path));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsGetAttrCache(abspath, attr);
+ LOG(4, ("Retrieve attr from cache. result = %d \n", res));
+ if (res != 0) {
+ /* Retrieve new complete attribute settings and update the cache. */
+ res = HgfsPrivateGetattr(fileHandle, abspath, attr);
+ LOG(4, ("Retrieve attr from server. result = %d \n", res));
+ if (res == 0 ) {
+ HgfsSetAttrCache(abspath, attr);
+ }
+ }
+
+ if (res < 0) {
+ goto exit;
+ }
+
+ LOG(4, ("fill stat for %s\n", abspath));
+
+ memset(stbuf, 0, sizeof *stbuf);
+
+ if (attr->mask & HGFS_ATTR_VALID_SPECIAL_PERMS) {
+ stbuf->st_mode |= (attr->specialPerms << 9);
+ }
+ if (attr->mask & HGFS_ATTR_VALID_OWNER_PERMS) {
+ stbuf->st_mode |= (attr->ownerPerms << 6);
+ }
+ if (attr->mask & HGFS_ATTR_VALID_GROUP_PERMS) {
+ stbuf->st_mode |= (attr->groupPerms << 3);
+ }
+ if (attr->mask & HGFS_ATTR_VALID_OTHER_PERMS) {
+ stbuf->st_mode |= (attr->otherPerms);
+ }
+
+ /* Mask the access mode. */
+ switch (attr->type) {
+ case HGFS_FILE_TYPE_SYMLINK:
+ d_type = DT_LNK;
+ break;
+
+ case HGFS_FILE_TYPE_REGULAR:
+ d_type = DT_REG;
+ break;
+
+ case HGFS_FILE_TYPE_DIRECTORY:
+ d_type = DT_DIR;
+ break;
+
+ default:
+ d_type = DT_UNKNOWN;
+ break;
+ }
+
+ stbuf->st_mode |= d_type << 12;
+ stbuf->st_blksize = HGFS_BLOCKSIZE;
+ stbuf->st_blocks = HgfsCalcBlockSize(attr->size);
+ stbuf->st_size = attr->size;
+ stbuf->st_ino = attr->hostFileId;
+ stbuf->st_nlink = 1;
+ stbuf->st_uid = attr->userId;
+ stbuf->st_gid = attr->groupId;
+ stbuf->st_rdev = 0;
+
+ if (attr->mask & HGFS_ATTR_VALID_ACCESS_TIME) {
+ HGFS_SET_TIME(stbuf->st_atime, attr->accessTime);
+ }
+ if (attr->mask & HGFS_ATTR_VALID_WRITE_TIME) {
+ HGFS_SET_TIME(stbuf->st_mtime, attr->writeTime);
+ }
+ if (attr->mask & HGFS_ATTR_VALID_CHANGE_TIME) {
+ HGFS_SET_TIME(stbuf->st_ctime, attr->attrChangeTime);
+ }
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_access
+ *
+ * Dummy routine, not fully implemented.
+ *
+ * Results:
+ * Returns zero.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_access(const char *path, //IN: Path to a file.
+ int mask) //IN: Mask
+{
+ HgfsHandle fileHandle = HGFS_INVALID_HANDLE;
+ HgfsAttrInfo newAttr = {0};
+ HgfsAttrInfo *attr = &newAttr;
+ uint32 effectivePermissions;
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s, mask = %#o)\n", path, mask));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsGetAttrCache(path, attr);
+ LOG(4, ("Retrieve attr from cache. result = %d \n", res));
+ if (res != 0) {
+ /* Retrieve new complete attribute settings and update the cache. */
+ res = HgfsPrivateGetattr(fileHandle, abspath, attr);
+ LOG(4, ("Retrieve attr from server. result = %d \n", res));
+ if (res == 0 ) {
+ HgfsSetAttrCache(abspath, attr);
+ }
+ }
+
+ if (res < 0) {
+ goto exit;
+ }
+
+ if (mask == F_OK) {
+ res = 0; /* assume the above attr retrieval did the validation */
+ goto exit;
+ }
+
+ if (attr->mask & HGFS_ATTR_VALID_EFFECTIVE_PERMS) {
+ effectivePermissions = attr->effectivePerms;
+ } else {
+ /*
+ * If the server did not return actual effective permissions then
+ * need to calculate ourselves. However we should avoid unnecessary
+ * denial of access so perform optimistic permissions calculation.
+ * It is safe since host enforces necessary restrictions regardless of
+ * the client's decisions.
+ */
+ effectivePermissions = (attr->ownerPerms |
+ attr->groupPerms |
+ attr->otherPerms);
+ }
+
+ if ((effectivePermissions & mask) != mask) {
+ res = -EACCES;
+ }
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_readlink
+ *
+ * Read the file pointed by the symbolic link.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_readlink(const char *path, //IN: path to a file
+ char *buf, //OUT: buffer to store the filename
+ size_t size) //IN: size of buf
+{
+ char *abspath = NULL;
+ int res = 0;
+ HgfsHandle fileHandle = 0;
+ HgfsAttrInfo newAttr = {0};
+ HgfsAttrInfo *attr = &newAttr;
+
+ LOG(4, ("Entry(path = %s, %#"FMTSZ"x)\n", path, size));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ /* The attributes fileName field will hold the symlink target name. */
+ res = HgfsPrivateGetattr(fileHandle, abspath, attr);
+ LOG(4, ("ReadLink: Path = %s, attr->fileName = %s \n", abspath, attr->fileName));
+ if (res < 0) {
+ goto exit;
+ }
+
+ if (size >= strlen(attr->fileName)) {
+ Str_Strcpy(buf, attr->fileName + gState->basePathLen,
+ strlen(attr->fileName) + 1 - gState->basePathLen);
+ } else {
+ res = -ENOBUFS;
+ }
+
+exit:
+ free(attr->fileName);
+ freeAbsPath(abspath);
+ LOG(4, ("Exit(%d)\n", res));
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_readdir
+ *
+ * Read the directoy file.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_readdir(const char *path, //IN: path to a directory
+ void *buf, //OUT: buffer to fill the dir entry
+ fuse_fill_dir_t filler, //IN: function pointer to fill buf
+ off_t offset, //IN: offset to read the dir
+ struct fuse_file_info *fi) //IN: file info set by open call
+{
+ char *abspath = NULL;
+ int res = 0;
+ HgfsHandle fileHandle = HGFS_INVALID_HANDLE;
+
+ LOG(4, ("Entry(path = %s, @ %#"FMT64"x)\n", path, offset));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsDirOpen(abspath, &fileHandle);
+ if (res < 0) {
+ goto exit;
+ }
+
+ fi->fh = fileHandle;
+ res = HgfsReaddir(fileHandle, buf, filler);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_mknod
+ *
+ * Dummy routine.
+ *
+ * Results:
+ * Returns -1.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_mknod(const char *path, //IN: Path to a file
+ mode_t mode, //IN: Mode to set
+ dev_t rdev) //IN: Device type
+{
+#if defined(__APPLE__)
+ LOG(4, ("Entry(path = %s, mode = %#o, %u)\n", path, mode, rdev));
+#else
+ LOG(4, ("Entry(path = %s, mode = %#o, %"FMT64"u)\n", path, mode, rdev));
+#endif
+ LOG(4, ("Dummy routine. Not implemented!"));
+ LOG(4, ("Exit(0)\n"));
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_mkdir
+ *
+ * Create directory.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_mkdir(const char *path, //IN: path to a new dir
+ mode_t mode) //IN: Mode of dir to be created
+{
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s, mode = %#o)\n", path, mode));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsMkdir(abspath, mode);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_unlink
+ *
+ * Delete file.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_unlink(const char *path) //IN: path to a file
+{
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s)\n", path));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsDelete(abspath, HGFS_OP_DELETE_FILE);
+ HgfsInvalidateAttrCache(abspath);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_rmdir
+ *
+ * Delete directory.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_rmdir(const char *path) //IN: path to a dir
+{
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s)\n", path));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsDelete(abspath, HGFS_OP_DELETE_DIR);
+ HgfsInvalidateAttrCache(abspath);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_symlink
+ *
+ * Create symbolic link.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_symlink(const char *from, //IN: from path
+ const char *to) //IN: to path
+{
+ char *absfrom = NULL;
+ char *absto = NULL;
+ int res;
+
+ LOG(4, ("Entry(from = %s, to = %s)\n", from, to));
+ res = getAbsPath(from, &absfrom);
+ if (res < 0) {
+ goto exit;
+ }
+ res = getAbsPath(to, &absto);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsSymlink(absto, absfrom);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(absfrom);
+ freeAbsPath(absto);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_rename
+ *
+ * Rename file or directory.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_rename(const char *from, //IN: from path name
+ const char *to) //IN: to path name
+{
+ char *absfrom = NULL;
+ char *absto = NULL;
+ int res;
+
+ LOG(4, ("Entry(from = %s, to = %s)\n", from, to));
+ res = getAbsPath(from, &absfrom);
+ if (res < 0) {
+ goto exit;
+ }
+ res = getAbsPath(to, &absto);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsRename(absfrom, absto);
+ HgfsInvalidateAttrCache(absfrom);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(absfrom);
+ freeAbsPath(absto);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_link
+ *
+ * Dummy routine.
+ *
+ * Results:
+ * Returns -1.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_link(const char *from, //IN: From path
+ const char *to) //IN: To path
+{
+ char *absfrom = NULL;
+ char *absto = NULL;
+ int res = 0;
+
+ LOG(4, ("Entry(from = %s, to = %s)\n", from, to));
+ res = getAbsPath(from, &absfrom);
+ if (res < 0) {
+ goto exit;
+ }
+ res = getAbsPath(to, &absto);
+ if (res < 0) {
+ goto exit;
+ }
+
+ /*Do nothing.*/
+ res = -1;
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(absfrom);
+ freeAbsPath(absto);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_chmod
+ *
+ * Change access mode of a file.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_chmod(const char *path, //IN: path to a file
+ mode_t mode) //IN: mode to set
+{
+ char *abspath = NULL;
+ int res;
+ HgfsHandle fileHandle = HGFS_INVALID_HANDLE;
+ HgfsAttrInfo newAttr = {0};
+ HgfsAttrInfo *attr = &newAttr;
+
+ LOG(4, ("Entry(path = %s, mode = %#o)\n", path, mode));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ attr->mask = (HGFS_ATTR_VALID_SPECIAL_PERMS |
+ HGFS_ATTR_VALID_OWNER_PERMS |
+ HGFS_ATTR_VALID_GROUP_PERMS |
+ HGFS_ATTR_VALID_OTHER_PERMS);
+ attr->specialPerms = (mode & (S_ISUID | S_ISGID | S_ISVTX)) >> 9;
+ attr->ownerPerms = (mode & S_IRWXU) >> 6;
+ attr->groupPerms = (mode & S_IRWXG) >> 3;
+ attr->otherPerms = mode & S_IRWXO;
+
+ attr->mask |= HGFS_ATTR_VALID_ACCESS_TIME;
+ attr->accessTime = attr->attrChangeTime = HGFS_GET_TIME(time(NULL));
+
+ res = HgfsSetattr(abspath, attr);
+ if (res < 0) {
+ LOG(4, ("path = %s , HgfsSetattr failed. res = %d\n", abspath, res));
+ goto exit;
+ }
+
+ /* Retrieve new complete attribute settings and update the cache. */
+ res = HgfsPrivateGetattr(fileHandle, abspath, attr);
+ if (res < 0) {
+ LOG(4, ("path = %s , res = %d\n", abspath, res));
+ goto exit;
+ }
+ HgfsSetAttrCache(abspath, attr);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_chown
+ *
+ * Change uid or gid of a file.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_chown(const char *path, //IN: Path to a file
+ uid_t uid, //IN: User id
+ gid_t gid) //IN: Group id
+{
+ HgfsHandle fileHandle = HGFS_INVALID_HANDLE;
+ HgfsAttrInfo newAttr = {0};
+ HgfsAttrInfo *attr = &newAttr;
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s, uid = %u, gid = %u)\n", abspath, uid, gid));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ attr->mask = HGFS_ATTR_VALID_USERID;
+ attr->userId = uid;
+
+ attr->mask |= HGFS_ATTR_VALID_GROUPID;
+ attr->groupId = gid;
+
+ attr->mask |= HGFS_ATTR_VALID_ACCESS_TIME;
+ attr->accessTime = attr->attrChangeTime = HGFS_GET_TIME(time(NULL));
+
+ res = HgfsSetattr(abspath, attr);
+ if (res < 0) {
+ LOG(4, ("path = %s , HgfsSetattr failed. res = %d\n", abspath, res));
+ goto exit;
+ }
+
+ /* Retrieve new complete attribute settings and update the cache. */
+ res = HgfsPrivateGetattr(fileHandle, abspath, attr);
+ if (res < 0) {
+ LOG(4, ("path = %s , res = %d\n", abspath, res));
+ goto exit;
+ }
+ HgfsSetAttrCache(abspath, attr);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_truncate
+ *
+ * Truncate a file to the given size.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_truncate(const char *path, //IN: path to a file
+ off_t size) //IN: new size
+{
+ HgfsHandle fileHandle = HGFS_INVALID_HANDLE;
+ HgfsAttrInfo newAttr = {0};
+ HgfsAttrInfo *attr = &newAttr;
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s, size %"FMT64"x)\n", path, size));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ attr->mask = HGFS_ATTR_VALID_SIZE;
+ attr->size = size;
+
+ attr->mask |= (HGFS_ATTR_VALID_WRITE_TIME |
+ HGFS_ATTR_VALID_ACCESS_TIME |
+ HGFS_ATTR_VALID_CHANGE_TIME);
+ attr->writeTime = attr->accessTime = attr->attrChangeTime = HGFS_GET_TIME(time(NULL));
+
+ res = HgfsSetattr(abspath, attr);
+ if (res < 0) {
+ LOG(4, ("path = %s , HgfsSetattr failed. res = %d\n", abspath, res));
+ goto exit;
+ }
+
+ /* Retrieve new complete attribute settings and update the cache. */
+ res = HgfsPrivateGetattr(fileHandle, abspath, attr);
+ if (res < 0) {
+ LOG(4, ("path = %s , res = %d\n", abspath, res));
+ goto exit;
+ }
+ HgfsSetAttrCache(abspath, attr);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_utimens/hgfs_utime
+ *
+ * Update access and write time of a file.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef HAVE_UTIMENSAT
+static int
+hgfs_utimens(const char *path, //IN: path to a file
+ const struct timespec ts[2]) //IN: new time
+#else
+static int
+hgfs_utime(const char *path, //IN: path to a file
+ struct utimbuf *times) //IN: new time
+#endif
+{
+ HgfsHandle fileHandle = HGFS_INVALID_HANDLE;
+ HgfsAttrInfo newAttr = {0};
+ HgfsAttrInfo *attr = &newAttr;
+ time_t accessTimeSec, accessTimeNsec, writeTimeSec, writeTimeNsec;
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s)\n", path));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsGetAttrCache(abspath, attr);
+ LOG(4, ("Retrieve attr from cache. result = %d \n", res));
+ if (res != 0) {
+ /* Retrieve new complete attribute settings and update the cache. */
+ res = HgfsPrivateGetattr(fileHandle, abspath, attr);
+ LOG(4, ("Retrieve attr from server. result = %d \n", res));
+ if (res == 0 ) {
+ HgfsSetAttrCache(abspath, attr);
+ }
+ }
+
+ if (res != 0) {
+ /* Failed to retrieve file attributes. */
+ goto exit;
+ }
+
+ if (attr->type == HGFS_FILE_TYPE_SYMLINK) {
+ /*
+ * utimensat() has a 'flag' parameter which is not available in fuse.
+ * by default, let's assume AT_SYMLINK_NOFOLLOW. but since there is
+ * neither a way to pass not 'followSymlinks' to setattr, let's simply
+ * do nothing for symlink.
+ */
+ goto exit;
+ }
+
+ attr->mask = (HGFS_ATTR_VALID_WRITE_TIME |
+ HGFS_ATTR_VALID_ACCESS_TIME);
+
+#ifdef HAVE_UTIMENSAT
+ accessTimeSec = ts[0].tv_sec;
+ accessTimeNsec = ts[0].tv_nsec;
+ writeTimeSec = ts[1].tv_sec;
+ writeTimeNsec = ts[1].tv_nsec;
+#else
+ accessTimeSec = times->actime;
+ accessTimeNsec = 0;
+ writeTimeSec = times->modtime;
+ writeTimeNsec = 0;
+#endif
+ attr->accessTime = HgfsConvertToNtTime(accessTimeSec, accessTimeNsec);
+ attr->writeTime = HgfsConvertToNtTime(writeTimeSec, writeTimeNsec);
+
+ res = HgfsSetattr(abspath, attr);
+ if (res < 0) {
+ LOG(4, ("abspath = %s , HgfsSetattr failed. res = %d\n", abspath, res));
+ goto exit;
+ }
+
+ /* Retrieve new complete attribute settings and update the cache. */
+ res = HgfsPrivateGetattr(fileHandle, abspath, attr);
+ if (res < 0) {
+ LOG(4, ("abspath = %s , res = %d\n", abspath, res));
+ goto exit;
+ }
+ HgfsSetAttrCache(abspath, attr);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_open
+ *
+ * Open file at a given path.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_open(const char *path, //IN: path to a file
+ struct fuse_file_info *fi) //IN: file info structure
+{
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s)\n", path));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsOpen(abspath, fi);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_create
+ *
+ * Create a new file, we do it by calling HgfsOpen.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_create(const char *path, //IN: path to a file
+ mode_t mode, //IN: file mode
+ struct fuse_file_info *fi) //IN: file info structure
+{
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s, mode = %#o)\n", path, mode));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsCreate(abspath, mode, fi);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_read
+ *
+ * Read the file using the handle, if the handle is zero
+ * then open the file first and then read.
+ *
+ * Results:
+ * Returns the number of bytes read from the file.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_read(const char *path, //IN: path to a file
+ char *buf, //OUT: to store the data
+ size_t size, //IN: size to read
+ off_t offset, //IN: starting point to read
+ struct fuse_file_info *fi) //IN: file info structure
+{
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s, fi->fh = %#"FMT64"x, %#"FMTSZ"x bytes @ %#"FMT64"x)\n",
+ path, fi->fh, size, offset));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ if (fi->fh == HGFS_INVALID_HANDLE) {
+ res = HgfsOpen(abspath, fi);
+ if (res) {
+ goto exit;
+ }
+ }
+ res = HgfsRead(fi, buf, size, offset);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_write
+ *
+ * Write to the file using the handle, if the handle is zero
+ * then open the file first and then write.
+ *
+ * Results:
+ * Returns the number of bytes written to the file.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_write(const char *path, //IN: path to a file
+ const char *buf, //IN: data to write
+ size_t size, //IN: size to write
+ off_t offset, //IN: starting point to write
+ struct fuse_file_info *fi) //IN: file info structure
+{
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s, fi->fh = %#"FMT64"x, write %#"FMTSZ"x bytes @ %#"FMT64"x)\n",
+ path, fi->fh, size, offset));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ if (fi->fh == HGFS_INVALID_HANDLE) {
+ res = HgfsOpen(abspath, fi);
+ if (res) {
+ goto exit;
+ }
+ }
+
+ res = HgfsWrite(fi, buf, size, offset);
+ HgfsInvalidateAttrCache(abspath);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_statfs
+ *
+ * Stat the host for total and free bytes on disk.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_statfs(const char *path, //IN: Path to the filesystem
+ struct statvfs *stbuf) //OUT:Struct to fill data
+{
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s)\n", path));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsStatfs(abspath, stbuf);
+
+exit:
+ LOG(4, ("Exit(%d)\n", res));
+ freeAbsPath(abspath);
+ return res;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_release
+ *
+ * Release a file.
+ *
+ * Results:
+ * Returns zero.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+hgfs_release(const char *path, //IN: path to a file
+ struct fuse_file_info *fi) //IN: file info structure
+{
+ char *abspath = NULL;
+ int res;
+
+ LOG(4, ("Entry(path = %s, fi->fh = %#"FMT64"x)\n", path, fi->fh));
+ res = getAbsPath(path, &abspath);
+ if (res < 0) {
+ goto exit;
+ }
+
+ res = HgfsRelease(fi->fh);
+ if (0 == res) {
+ fi->fh = HGFS_INVALID_HANDLE;
+ }
+
+exit:
+ LOG(4, ("Exit(0)\n"));
+ freeAbsPath(abspath);
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_init
+ *
+ * Initialization routine. We spawn the cache purge thread here.
+ *
+ * Results:
+ * Returns NULL.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void*
+hgfs_init(struct fuse_conn_info *conn) // IN: unused
+{
+ pthread_t purgeCacheThread;
+ int dummy;
+ int res;
+
+ LOG(4, ("Entry()\n"));
+
+ /*
+ * dummy argument is required for Solaris and FreeBSD while creating
+ * thread otherwise the program crashes.
+ */
+ res = pthread_create(&purgeCacheThread, NULL,
+ HgfsPurgeCache, &dummy);
+ if (res < 0) {
+ LOG(4, ("Pthread create fail. error = %d\n", res));
+ }
+
+ res = HgfsCreateSession();
+ if (res < 0) {
+ LOG(4, ("Create session failed. error = %d\n", res));
+ }
+
+ LOG(4, ("Exit(NULL)\n"));
+ return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hgfs_destroy
+ *
+ * Cleanup routine.
+ *
+ * Results:
+ * Returns NULL.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+hgfs_destroy(void *data) // IN: unused
+{
+ int res;
+
+ LOG(4, ("Entry()\n"));
+
+ res = HgfsDestroySession();
+ free(gState->basePath);
+
+ if (res < 0) {
+ LOG(4, ("Destroy session failed. error = %d\n", res));
+ }
+
+ LOG(4, ("Exit()\n"));
+}
+
+
+/*--------------------------------------------------------------------------- */
+static struct fuse_operations vmhgfs_operations = {
+ .getattr = hgfs_getattr,
+ .access = hgfs_access,
+ .readlink = hgfs_readlink,
+ .readdir = hgfs_readdir,
+ .mknod = hgfs_mknod,
+ .mkdir = hgfs_mkdir,
+ .symlink = hgfs_symlink,
+ .unlink = hgfs_unlink,
+ .rmdir = hgfs_rmdir,
+ .rename = hgfs_rename,
+ .link = hgfs_link,
+ .chmod = hgfs_chmod,
+ .chown = hgfs_chown,
+ .truncate = hgfs_truncate,
+#ifdef HAVE_UTIMENSAT
+ .utimens = hgfs_utimens,
+#else // HAVE_UTIMENSAT
+ .utime = hgfs_utime,
+#endif // defined HAVE_UTIMENSAT
+ .open = hgfs_open,
+ .read = hgfs_read,
+ .write = hgfs_write,
+ .statfs = hgfs_statfs,
+ .release = hgfs_release,
+ .create = hgfs_create,
+ .init = hgfs_init,
+ .destroy = hgfs_destroy,
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * main
+ *
+ * Starting point of the program.
+ *
+ * Results:
+ * Returns zero on success, or a negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+main(int argc, //IN: Argument count
+ char *argv[]) //IN: Argument list
+{
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ int res;
+
+ res = vmhgfsPreprocessArgs(&args);
+ if (res != 0) {
+ fprintf(stderr, "Error parsing arguments!\n");
+ exit(1);
+ }
+
+ /* Initialization */
+ umask(0);
+ HgfsResetOps();
+ res = HgfsTransportInit();
+ if (res != 0) {
+ LOG(4, ("Main: Error in HgfsTransportInit %d\n", res));
+ return res;
+ }
+ HgfsInitCache();
+
+ return fuse_main(args.argc, args.argv, &vmhgfs_operations, NULL);
+}
+
diff --git a/open-vm-tools/vmhgfs-fuse/module.h b/open-vm-tools/vmhgfs-fuse/module.h
new file mode 100644
index 00000000..922120e0
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/module.h
@@ -0,0 +1,132 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * module.h --
+ *
+ * Global module definitions for the entire FUSE based HGFS
+ */
+
+#ifndef _VMHGFS_FUSE_MODULE_H_
+#define _VMHGFS_FUSE_MODULE_H_
+
+#define FUSE_USE_VERSION 29
+
+#include <sys/types.h>
+#include "hgfsUtil.h"
+#include "vm_assert.h"
+#include <stdlib.h>
+#include "vm_assert.h"
+#include "cpName.h"
+#include "cpNameLite.h"
+#include "hgfsUtil.h"
+#include "request.h"
+#include "fsutil.h"
+#include "filesystem.h"
+#include "vm_basic_types.h"
+#include "vmhgfs_version.h"
+#include "vmware.h"
+#include "str.h"
+#include "codeset.h"
+#include "rpcout.h"
+#include "hgfsProto.h"
+#include <errno.h>
+#include <linux/list.h>
+#include <stdio.h>
+#include <fuse.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/time.h>
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#endif
+#include <sys/stat.h>
+#ifndef __SOLARIS__
+#include <sys/types.h>
+#endif
+
+#include "transport.h"
+#include "session.h"
+#include "config.h"
+
+#if defined(__SOLARIS__) || defined(__APPLE__)
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+#define NAME_MAX 255 /* # chars in a file name */
+#endif
+
+#include "hgfsEscape.h"
+
+#ifdef VMX86_DEVEL
+extern int LOGLEVEL_THRESHOLD;
+
+#define LGPFX "vmhgfs-fuse"
+#define LGPFX_FMT "%s:%s:"
+
+#define LOG(level, args) \
+ do { \
+ if (level <= LOGLEVEL_THRESHOLD) { \
+ Log(LGPFX_FMT, LGPFX, __FUNCTION__); \
+ Log args; \
+ } \
+ } while (0)
+
+#else
+#define LOG(level, args)
+#endif
+
+/* Blocksize to be set in superblock. (XXX how is this used?) */
+#define HGFS_BLOCKSIZE 1024
+
+#define HGFS_SET_TIME(unixtm,nttime) HgfsConvertFromNtTime(&unixtm, nttime)
+#define HGFS_GET_TIME(unixtm) HgfsConvertToNtTime(unixtm, 0L)
+#define HGFS_GET_CURRENT_TIME() HgfsConvertToNtTime(CURRENT_TIME, 0L)
+/*
+ * Global synchronization primitives.
+ */
+
+/* Other global state. */
+extern HgfsOp hgfsVersionCreateSession;
+extern HgfsOp hgfsVersionDestroySession;
+extern HgfsOp hgfsVersionOpen;
+extern HgfsOp hgfsVersionRead;
+extern HgfsOp hgfsVersionWrite;
+extern HgfsOp hgfsVersionClose;
+extern HgfsOp hgfsVersionSearchOpen;
+extern HgfsOp hgfsVersionSearchRead;
+extern HgfsOp hgfsVersionSearchClose;
+extern HgfsOp hgfsVersionGetattr;
+extern HgfsOp hgfsVersionSetattr;
+extern HgfsOp hgfsVersionCreateDir;
+extern HgfsOp hgfsVersionDeleteFile;
+extern HgfsOp hgfsVersionDeleteDir;
+extern HgfsOp hgfsVersionRename;
+extern HgfsOp hgfsVersionQueryVolumeInfo;
+extern HgfsOp hgfsVersionCreateSymlink;
+
+extern HgfsFuseState *gState;
+
+#endif // _VMHGFS_FUSE_MODULE_H_
diff --git a/open-vm-tools/vmhgfs-fuse/request.c b/open-vm-tools/vmhgfs-fuse/request.c
new file mode 100644
index 00000000..491cec90
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/request.c
@@ -0,0 +1,448 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * request.c --
+ *
+ * Functions dealing with the creation, deletion, and sending of HGFS
+ * requests are defined here.
+ */
+
+#include "linux/list.h"
+#include "module.h"
+#include "request.h"
+#include "transport.h"
+#include "fsutil.h"
+#include "vm_assert.h"
+
+static HgfsHandle hgfsIdCounter;
+pthread_mutex_t hgfsIdLock = PTHREAD_MUTEX_INITIALIZER;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetNewRequest --
+ *
+ * Get a new request structure off the free list and initialize it.
+ *
+ * Results:
+ * On success the new struct is returned with all fields
+ * initialized. Returns NULL on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+HgfsReq *
+HgfsGetNewRequest(void)
+{
+ HgfsReq *req = NULL;
+
+ req = (HgfsReq*)malloc(sizeof(HgfsReq));
+ if (req == NULL) {
+ LOG(4, ("Can't allocate memory.\n"));
+ return NULL;
+ }
+ INIT_LIST_HEAD(&req->list);
+ req->payloadSize = 0;
+ req->state = HGFS_REQ_STATE_ALLOCATED;
+ /* Setup the packet prefix. */
+ memcpy(req->packet, HGFS_SYNC_REQREP_CLIENT_CMD,
+ HGFS_SYNC_REQREP_CLIENT_CMD_LEN);
+ pthread_mutex_lock(&hgfsIdLock);
+ req->id = hgfsIdCounter;
+ hgfsIdCounter++;
+ pthread_mutex_unlock(&hgfsIdLock);
+
+ return req;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsPackHeader --
+ *
+ * Fill the header fields for the request. If session is enabled,
+ * use new header.
+ *
+ * Results:
+ * HGFS_STATUS_SUCCESS for a valid header
+ * else HGFS_STATUS_PROTOCOL_ERROR
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+HgfsStatus
+HgfsPackHeader(HgfsReq *req, // IN/OUT:
+ HgfsOp opUsed) // IN
+{
+ if (gState->sessionEnabled) { /* use new header */
+ HgfsHeader *header = (HgfsHeader*)HGFS_REQ_PAYLOAD(req);
+
+ LOG(4, ("sessionEnabled, use HgfsHeader. opUsed = %d\n", opUsed));
+ header->version = gState->headerVersion;
+ header->dummy = HGFS_OP_NEW_HEADER;
+ header->headerSize = sizeof *header;
+ header->packetSize = req->payloadSize;
+ header->requestId = req->id;
+ header->op = opUsed;
+ header->sessionId = gState->sessionId;
+ header->flags = HGFS_PACKET_FLAG_REQUEST;
+ /*
+ * Currently unused fields which can be used in version 2 and later.
+ * Version 1 didn't zero these fields, hence the server cannot determine
+ * their validity.
+ */
+ header->status = 0;
+ header->information = 0;
+ header->reserved = 0;
+ memset(&header->reserved1[0], 0, sizeof header->reserved1);
+
+ } else {
+ HgfsRequest *header = (HgfsRequest*)HGFS_REQ_PAYLOAD(req);
+
+ LOG(4, ("not sessionEnabled, use HgfsRequest. opUsed = %d\n", opUsed));
+ header->id = req->id;
+ header->op = opUsed;
+ }
+
+ return HGFS_STATUS_SUCCESS;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsUnpackHeader --
+ *
+ * Validate that server reply contains valid HgfsHeader that matches
+ * current session.
+ * Extract various useful fields from the protocol header of the reply.
+ *
+ * Results:
+ * HGFS_STATUS_SUCCESS for a valid header
+ * else HGFS_STATUS_PROTOCOL_ERROR
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+HgfsStatus
+HgfsUnpackHeader(void *serverReply, // IN: server reply
+ size_t replySize, // IN: reply data size
+ uint8 *headerVersion, // OUT: version
+ uint64 *sessionId, // OUT: unique session id
+ uint32 *requestId, // OUT: unique request id
+ uint32 *headerFlags, // OUT: header flags
+ uint32 *information, // OUT: generic information
+ HgfsOp *opcode, // OUT: request opcode
+ HgfsStatus *replyStatus, // OUT: reply status
+ void **payload, // OUT: pointer to the payload
+ size_t *payloadSize) // OUT: size of the payload
+{
+ HgfsHeader *header = (HgfsHeader *)serverReply;
+
+ /* First some sanity checking. */
+ if ((replySize < sizeof (HgfsHeader)) ||
+ (header->dummy != HGFS_OP_NEW_HEADER) ||
+ (header->packetSize > replySize) ||
+ (header->headerSize > header->packetSize)) {
+ return HGFS_STATUS_PROTOCOL_ERROR;
+ }
+
+ *headerVersion = header->version;
+ *sessionId = header->sessionId;
+ *requestId = header->requestId;
+ *opcode = header->op;
+ *headerFlags = header->flags;
+ *information = header->information;
+ *payloadSize = header->packetSize - header->headerSize;
+ if (*payloadSize) {
+ *payload = (char *)serverReply + header->headerSize;
+ } else {
+ *payload = NULL;
+ }
+
+ *replyStatus = header->status;
+
+ return HGFS_STATUS_SUCCESS;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetRequestPayload --
+ *
+ * Results:
+ * Returns a pointer to the start of the payload data.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+INLINE void*
+HgfsGetRequestPayload(HgfsReq *req) // IN:
+{
+ if (gState->sessionEnabled) {
+ return (void*) HGFS_REQ_GET_PAYLOAD_HDRV2(req);
+ } else {
+ return (void*) HGFS_REQ_PAYLOAD_V3(req);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetReplyPayload --
+ *
+ * Results:
+ * Returns a pointer to the start of the payload data.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+INLINE void*
+HgfsGetReplyPayload(HgfsReq *rep) // IN:
+{
+ if (gState->sessionEnabled) {
+ return (void*) HGFS_REP_GET_PAYLOAD_HDRV2(rep);
+ } else {
+ return (void*) HGFS_REP_PAYLOAD_V3(rep);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetRequestHeaderSize --
+ *
+ * Results:
+ * The size of request message header.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+INLINE size_t
+HgfsGetRequestHeaderSize(void)
+{
+ return (gState->sessionEnabled ?
+ sizeof(HgfsHeader) :
+ sizeof(HgfsRequest));
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetReplyHeaderSize --
+ *
+ * Results:
+ * The size of reply message header.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+INLINE size_t
+HgfsGetReplyHeaderSize(void)
+{
+ return (gState->sessionEnabled ?
+ sizeof(HgfsHeader) :
+ sizeof(HgfsReply));
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsSendRequest --
+ *
+ * Send out an HGFS request via transport layer, and wait for the reply.
+ *
+ * Results:
+ * Returns zero on success, negative number on error.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsSendRequest(HgfsReq *req) // IN/OUT: Outgoing request
+{
+ int ret;
+
+ ASSERT(req);
+ ASSERT(req->payloadSize <= HGFS_LARGE_PACKET_MAX);
+
+ req->state = HGFS_REQ_STATE_UNSENT;
+
+ LOG(8, ("Sending request id %d\n", req->id));
+ LOG(4, ("Before sending \n"));
+
+ ret = HgfsTransportSendRequest(req);
+ LOG(4, ("After sending \n"));
+
+ LOG(8, ("Request finished, return %d\n", ret));
+ return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsFreeRequest --
+ *
+ * Free an HGFS request.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+HgfsFreeRequest(HgfsReq *req) // IN: Request to free
+{
+ free(req);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsReplyStatus --
+ *
+ * Return reply status.
+ *
+ * Results:
+ * Returns reply status as per the protocol.
+ *
+ * Side effects:
+ * reestablish session when encounter session stale failure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+HgfsStatus
+HgfsGetReplyStatus(HgfsReq *req) // IN
+{
+ HgfsStatus status;
+
+ if (req->payloadSize < sizeof (HgfsReply)) {
+ LOG(4, ("Malformed packet received.\n"));
+ status = HGFS_STATUS_PROTOCOL_ERROR;
+ goto out;
+ }
+
+ if (gState->sessionEnabled &&
+ req->payloadSize < sizeof (HgfsHeader)) {
+ /*
+ * We have enabled an HGFS protocol session which uses the new header
+ * format. And an HGFS protocol session uses the new header format only.
+ * A reply without the new header indicates a message with the
+ * old reply header format.
+ */
+ gState->sessionEnabled = FALSE;
+ }
+
+ if (gState->sessionEnabled) {
+ HgfsHeader *header = (HgfsHeader *)(HGFS_REQ_PAYLOAD(req));
+ status = header->status;
+
+ if (status == HGFS_STATUS_STALE_SESSION) {
+ LOG(4, ("Session stale! Try to recreate session ...\n"));
+ HgfsCreateSession();
+ /*
+ * XXX: User might want to retry it later, and status will not be
+ * changed here. But due to the fail safe directory access like
+ * searching for dynamic library path, user hardly ever notice
+ * the failure.
+ */
+ }
+
+ } else {
+ HgfsReply *reply = (HgfsReply *)(HGFS_REQ_PAYLOAD(req));
+ status = reply->status;
+ }
+
+out:
+ LOG(4, ("Exit(status = %d)\n", status));
+ return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsCompleteReq --
+ *
+ * Copies the reply packet into the request structure and wakes up
+ * the associated client.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+HgfsCompleteReq(HgfsReq *req, // IN: Request
+ char const *reply, // IN: Reply packet
+ size_t replySize) // IN: Size of reply packet
+{
+ ASSERT(req);
+ ASSERT(reply);
+ ASSERT(replySize <= HGFS_LARGE_PACKET_MAX);
+
+ memcpy(HGFS_REQ_PAYLOAD(req), reply, replySize);
+ req->payloadSize = replySize;
+ req->state = HGFS_REQ_STATE_COMPLETED;
+ if (!list_empty(&req->list)) {
+ list_del_init(&req->list);
+ }
+}
diff --git a/open-vm-tools/vmhgfs-fuse/request.h b/open-vm-tools/vmhgfs-fuse/request.h
new file mode 100644
index 00000000..b11844a4
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/request.h
@@ -0,0 +1,138 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * request.h --
+ *
+ * Functions dealing with the creation, deletion, and sending of HGFS
+ * requests are defined here.
+ */
+
+#ifndef _VMHGFS_FUSE_REQUEST_H_
+#define _VMHGFS_FUSE_REQUEST_H_
+
+/* Must come before any kernel header file. */
+//#include "driver-config.h"
+
+#include <linux/list.h>
+//#include "compat_sched.h"
+//#include "compat_spinlock.h"
+//#include "compat_wait.h"
+
+#include "hgfs.h" /* For common HGFS definitions. */
+#include "hgfsProto.h"
+#include "vm_basic_types.h"
+
+/* Macros for accessing the payload portion of the HGFS request packet. */
+#define HGFS_REQ_PAYLOAD(hgfsReq) ((hgfsReq)->packet + HGFS_CLIENT_CMD_LEN)
+
+#define HGFS_REQ_PAYLOAD_V3(hgfsReq) (HGFS_REQ_PAYLOAD(hgfsReq) + sizeof(HgfsRequest))
+#define HGFS_REP_PAYLOAD_V3(hgfsRep) (HGFS_REQ_PAYLOAD(hgfsRep) + sizeof(HgfsReply))
+
+#define HGFS_REQ_GET_PAYLOAD_HDRV2(hgfsReq) (HGFS_REQ_PAYLOAD(hgfsReq) + sizeof(HgfsHeader))
+#define HGFS_REP_GET_PAYLOAD_HDRV2(hgfsRep) (HGFS_REQ_PAYLOAD(hgfsRep) + sizeof(HgfsHeader))
+
+
+/*
+ * HGFS_REQ_STATE_ALLOCATED:
+ * The filesystem half has allocated the request from the slab
+ * allocator. The request is not on any list.
+ *
+ * HGFS_REQ_STATE_UNSENT:
+ * The filesystem half of the driver has filled in the request fields
+ * and placed the request in the global unsent list. It is now the
+ * request handler's responsibility to submit this request to
+ * the channel. Requests in this state are on the global unsent list.
+ *
+ * HGFS_REQ_STATE_SUBMITTED:
+ * The packet has been sent, but the reply will arrive asynchronously.
+ * The request will be on the hgfsRepPending list, and whenever
+ * the reply arrives, the reply handler will remove the request from
+ * the hgfsRepPending list and stuff the reply into the request's
+ * packet buffer.
+ *
+ * This is only for asynchronous channel communication.
+ *
+ * HGFS_REQ_STATE_COMPLETED:
+ * The request handler sent the request and received a reply. The reply
+ * is stuffed in the request's packet buffer. Requests in this state
+ * are not on any list.
+ */
+typedef enum {
+ HGFS_REQ_STATE_ALLOCATED,
+ HGFS_REQ_STATE_UNSENT,
+ HGFS_REQ_STATE_SUBMITTED,
+ HGFS_REQ_STATE_COMPLETED,
+} HgfsState;
+
+/*
+ * A request to be sent to the user process.
+ */
+typedef struct HgfsReq {
+
+ /* Links to place the object on various lists. */
+ struct list_head list;
+
+ /*
+ * When clients wait for the reply to a request, they'll wait on this
+ * wait queue.
+ */
+ //wait_queue_head_t queue;
+
+ /* Current state of the request. */
+ HgfsState state;
+
+ /* ID of this request */
+ HgfsHandle id;
+
+ /* Total size of the payload.*/
+ size_t payloadSize;
+
+ /*
+ * Packet of data, for both incoming and outgoing messages.
+ * Include room for the command.
+ */
+ char packet[HGFS_LARGE_PACKET_MAX + HGFS_CLIENT_CMD_LEN];
+} HgfsReq;
+
+/* Public functions (with respect to the entire module). */
+HgfsReq *HgfsGetNewRequest(void);
+HgfsStatus HgfsPackHeader(HgfsReq *req, HgfsOp opUsed);
+HgfsStatus HgfsUnpackHeader(void *serverReply,
+ size_t replySize,
+ uint8 *headerVersion,
+ uint64 *sessionId,
+ uint32 *requestId,
+ uint32 *headerFlags,
+ uint32 *information,
+ HgfsOp *opcode,
+ HgfsStatus *replyStatus,
+ void **payload,
+ size_t *payloadSize);
+void* HgfsGetRequestPayload(HgfsReq *req);
+void* HgfsGetReplyPayload(HgfsReq *req);
+size_t HgfsGetReplyHeaderSize(void);
+size_t HgfsGetRequestHeaderSize(void);
+int HgfsSendRequest(HgfsReq *req);
+void HgfsFreeRequest(HgfsReq *req);
+HgfsStatus HgfsGetReplyStatus(HgfsReq *req);
+void HgfsCompleteReq(HgfsReq *req,
+ char const *reply,
+ size_t replySize);
+
+#endif // _VMHGFS_FUSE_REQUEST_H_
diff --git a/open-vm-tools/vmhgfs-fuse/session.c b/open-vm-tools/vmhgfs-fuse/session.c
new file mode 100644
index 00000000..0f4e51ed
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/session.c
@@ -0,0 +1,418 @@
+/*********************************************************
+ * Copyright (C) 2015 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * session.c --
+ *
+ * Hgfs session related operations.
+ */
+
+#include "module.h"
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsPackCreateSessionRequestV4 --
+ *
+ * Packs create session request to be sent to the server.
+ * This is the first request that is sent after a connection
+ * to a server had been established.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsPackCreateSessionRequest(HgfsOp opUsed, // IN: Op to be used
+ HgfsReq *req) // IN/OUT: Packet to write into
+{
+ switch (opUsed) {
+ case HGFS_OP_CREATE_SESSION_V4: {
+ HgfsRequestCreateSessionV4 *requestV4 = HgfsGetRequestPayload(req);
+
+ requestV4->numCapabilities = 0;
+ requestV4->maxPacketSize = HGFS_LARGE_PACKET_MAX;
+ requestV4->reserved = 0;
+
+ req->payloadSize = sizeof(*requestV4) + HgfsGetRequestHeaderSize();
+
+ break;
+ }
+ default:
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ return -EPROTO;
+ }
+
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsCreateSessionProcessResult --
+ *
+ * Process create session server reply.
+ *
+ * Results:
+ * HGFS_STATUS_SUCCESS if everything is right,
+ * else HGFS_STATUS_PROTOCOL_ERROR
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static HgfsStatus
+HgfsCreateSessionProcessResult(const char *result, // IN: Reply packet
+ size_t resultSize) // IN: packet size
+{
+ HgfsStatus status = HGFS_STATUS_SUCCESS;
+ uint64 sessionId = HGFS_INVALID_SESSION_ID;
+ uint8 headerVersion = HGFS_HEADER_VERSION_1;
+ Bool sessionIdPresent = FALSE;
+
+ uint32 information;
+ HgfsHandle requestId;
+ HgfsStatus tmpStatus;
+ uint32 headerFlags = 0;
+ HgfsOp op;
+ void *replyPayload;
+ size_t replyPayloadSize;
+ HgfsReplyCreateSessionV4 *createSessionReply;
+
+ tmpStatus = HgfsUnpackHeader((void *) result,
+ resultSize,
+ &headerVersion,
+ &sessionId,
+ &requestId,
+ &headerFlags,
+ &information,
+ &op,
+ &status,
+ &replyPayload,
+ &replyPayloadSize);
+ /* Older servers set the header flags to zero. */
+ if (0 != headerFlags) {
+ if (0 == (headerFlags & HGFS_PACKET_FLAG_REPLY)) {
+ /* The server request flag must be set for these packets. */
+ status = HGFS_STATUS_PROTOCOL_ERROR;
+ goto out;
+ }
+ }
+ if (tmpStatus != HGFS_STATUS_SUCCESS) {
+ LOG(4, ("Malformed packet received. status=%d\n", tmpStatus));
+ status = HGFS_STATUS_PROTOCOL_ERROR;
+ goto out;
+ }
+
+ if (status == HGFS_STATUS_SUCCESS) {
+ createSessionReply = (HgfsReplyCreateSessionV4 *) replyPayload;
+ ASSERT(createSessionReply);
+
+ LOG(4, ("Successfully created the session.\n"));
+
+ /*
+ * XXX: HgfsServer returns other properties like capabilities etc.
+ * in the reply. In the future, we should extend the
+ * structure to hold these properties returned from the HgfsServer
+ * for CreateSession request.
+ */
+ sessionId = createSessionReply->sessionId;
+ sessionIdPresent = TRUE;
+ }
+
+out:
+ gState->sessionId = sessionId;
+ gState->headerVersion = headerVersion;
+ gState->sessionEnabled = sessionIdPresent;
+
+ LOG(4, ("Exit(%d)\n", status));
+ return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsCreateSession --
+ *
+ * Sends a Create session request to the HGFS Server.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+HgfsCreateSession(void)
+{
+ HgfsReq *req;
+ int result;
+ HgfsStatus status;
+ HgfsOp opUsed;
+
+ LOG(4, ("Entry()\n"));
+ gState->sessionEnabled = TRUE;
+ gState->headerVersion = HGFS_HEADER_VERSION;
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request.\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+ opUsed = hgfsVersionCreateSession;
+ result = HgfsPackCreateSessionRequest(opUsed, req);
+ if (result != 0) {
+ LOG(4, ("Error packing request.\n"));
+ goto out;
+ }
+
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ LOG(6, ("Got reply.\n"));
+ status = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(status);
+ switch (result) {
+ case 0:
+ status = HgfsCreateSessionProcessResult(HGFS_REQ_PAYLOAD(req),
+ req->payloadSize);
+ ASSERT(status == HGFS_STATUS_SUCCESS);
+ break;
+ case -EPROTO:
+ /* Fallthrough. */
+ default:
+ LOG(6, ("Session was not created, error %d\n", result));
+ gState->sessionEnabled = FALSE;
+ break;
+ }
+
+ } else {
+ gState->sessionEnabled = FALSE;
+
+ if (result == -EIO) {
+ LOG(4, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+ }
+
+out:
+ HgfsFreeRequest(req);
+ LOG(4, ("Exit(%d)\n", result));
+ return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsPackDestroySessionRequestV4 --
+ *
+ * Packs destroy session request to be sent to the server.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsPackDestroySessionRequest(HgfsOp opUsed, // IN: Op to be used
+ HgfsReq *req) // IN/OUT: Packet to write into
+{
+ switch (opUsed) {
+ case HGFS_OP_DESTROY_SESSION_V4: {
+ HgfsRequestDestroySessionV4 *requestV4 =
+ (HgfsRequestDestroySessionV4*)HgfsGetRequestPayload(req);
+
+ requestV4->reserved = 0;
+
+ req->payloadSize = sizeof(HgfsHeader) + sizeof(*requestV4);
+ /* Fill in header here as payloadSize needs to be there. */
+ HgfsPackHeader(req, opUsed);
+
+ break;
+ }
+ default:
+ LOG(4, ("Unexpected OP type encountered. opUsed = %d\n", opUsed));
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsDestroySessionProcessResult --
+ *
+ * Process destroy session server reply.
+ *
+ * Results:
+ * HGFS_STATUS_SUCCESS if everything is right,
+ * else HGFS_STATUS_PROTOCOL_ERROR
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static HgfsStatus
+HgfsDestroySessionProcessResult(const char *result, // IN: Reply packet
+ size_t resultSize) // IN: packet size
+{
+ uint8 headerVersion = HGFS_HEADER_VERSION_1;
+ uint64 sessionId;
+ HgfsHandle requestId;
+ uint32 headerFlags = 0;
+ uint32 information;
+ HgfsOp op;
+ size_t payloadSize;
+ void *replyPayload;
+ HgfsStatus status = HGFS_STATUS_SUCCESS;
+ HgfsStatus tmpStatus;
+
+ tmpStatus = HgfsUnpackHeader((void *) result,
+ resultSize,
+ &headerVersion,
+ &sessionId,
+ &requestId,
+ &headerFlags,
+ &information,
+ &op,
+ &status,
+ &replyPayload,
+ &payloadSize);
+ if (tmpStatus != HGFS_STATUS_SUCCESS) {
+ LOG(4, ("%s: Malformed packet received.\n", __FUNCTION__));
+ status = HGFS_STATUS_PROTOCOL_ERROR;
+ goto out;
+ }
+
+ if(status == HGFS_STATUS_SUCCESS) {
+ LOG(4, ("Successfully destroyed the session.\n"));
+ }
+
+out:
+ gState->sessionId = HGFS_INVALID_SESSION_ID;
+ gState->sessionEnabled = FALSE;
+
+ LOG(4, ("Exit(%d)\n", status));
+ return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsDestroySession --
+ *
+ * Sends a Create session request to the HGFS Server in the guest.
+ *
+ * Results:
+ * Returns zero on success, or negative error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+HgfsDestroySession(void)
+{
+ HgfsReq *req;
+ int result;
+ HgfsStatus status;
+ HgfsOp opUsed;
+
+ LOG(4, ("Entry()\n"));
+ if (!gState->sessionEnabled) {
+ return 0;
+ }
+
+ req = HgfsGetNewRequest();
+ if (!req) {
+ LOG(4, ("Out of memory while getting new request.\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+ opUsed = hgfsVersionDestroySession;
+ result = HgfsPackDestroySessionRequest(opUsed, req);
+ if (result != 0) {
+ LOG(4, ("Error packing request.\n"));
+ goto out;
+ }
+
+ result = HgfsSendRequest(req);
+ if (result == 0) {
+ LOG(6, ("Got reply.\n"));
+ status = HgfsGetReplyStatus(req);
+ result = HgfsStatusConvertToLinux(status);
+ switch (result) {
+ case 0:
+ status = HgfsDestroySessionProcessResult(HGFS_REQ_PAYLOAD(req),
+ req->payloadSize);
+ ASSERT(status == HGFS_STATUS_SUCCESS);
+ break;
+ case -EPROTO:
+ /* Fallthrough. */
+ default:
+ LOG(6, ("Session was not created, error %d\n", result));
+ break;
+ }
+ } else if (result == -EIO) {
+ LOG(4, ("Timed out. error: %d\n", result));
+ } else if (result == -EPROTO) {
+ LOG(4, ("Server returned error: %d\n", result));
+ } else {
+ LOG(4, ("Unknown error: %d\n", result));
+ }
+
+out:
+ HgfsFreeRequest(req);
+ LOG(4, ("Exit(%d)\n", result));
+ return result;
+}
+
diff --git a/open-vm-tools/vmhgfs-fuse/session.h b/open-vm-tools/vmhgfs-fuse/session.h
new file mode 100644
index 00000000..cfed2d0a
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/session.h
@@ -0,0 +1,30 @@
+/*********************************************************
+ * Copyright (C) 2015 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * session.h --
+ *
+ */
+
+#ifndef _VMHGFS_FUSE_SESSION_H_
+#define _VMHGFS_FUSE_SESSION_H_
+
+int HgfsCreateSession(void);
+int HgfsDestroySession(void);
+
+#endif
diff --git a/open-vm-tools/vmhgfs-fuse/transport.c b/open-vm-tools/vmhgfs-fuse/transport.c
new file mode 100644
index 00000000..4878d368
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/transport.c
@@ -0,0 +1,421 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * transport.c --
+ *
+ * This file handles the transport mechanisms available for HGFS.
+ * This acts as a glue between the HGFS filesystem driver and the
+ * actual transport channels (backdoor, tcp, vsock, ...).
+ *
+ * The sends happen in the process context, where as a thread
+ * handles the asynchronous replies. A queue of pending replies is
+ * maintained and is protected by a lock. The channel opens and close
+ * is protected by a mutex.
+ */
+
+
+
+#include "bdhandler.h"
+#include "hgfsProto.h"
+#include "module.h"
+#include "request.h"
+#include "transport.h"
+#include "vm_assert.h"
+
+static HgfsTransportChannel *gHgfsActiveChannel; /* Current active channel. */
+static pthread_mutex_t gHgfsActiveChannelLock; /* Current active channel lock. */
+
+static struct list_head gHgfsPendingRequests; /* Pending requests queue. */
+static pthread_mutex_t gHgfsPendingRequestsLock; /* Pending requests queue lock. */
+
+
+#define HgfsRequestId(req) ((HgfsRequest *)req)->id
+
+static void HgfsTransportChannelClose(HgfsTransportChannel **channel);
+
+/*
+ * Private function implementations.
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportChannelOpen --
+ *
+ * Open a new workable channel.
+ *
+ * Results:
+ * TRUE on success and the new channel, otherwise FALSE and NULL.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+HgfsTransportChannelOpen(HgfsTransportChannel **channel) // IN: active channel
+{
+ Bool result = FALSE;
+
+ *channel = HgfsBdChannelInit();
+ if (NULL != *channel) {
+ if ((*channel)->ops.open(*channel)) {
+ result = TRUE;
+ } else {
+ HgfsTransportChannelClose(channel);
+ }
+ }
+
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportChannelClose --
+ *
+ * Teardown current channel and stop current receive thread.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsTransportChannelClose(HgfsTransportChannel **channel) // active channel
+{
+ if (NULL != *channel) {
+ HgfsTransportChannel *closeChannel = *channel;
+
+ closeChannel->ops.close(closeChannel);
+ closeChannel->ops.exit(closeChannel);
+ *channel = NULL;
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportChannelReset --
+ *
+ * Called when current channel doesn't work. Find a new channel
+ * for transport.
+ *
+ * Results:
+ * TRUE on success, otherwise FALSE;
+ *
+ * Side effects:
+ * Teardown current opened channel and the receive thread, set up
+ * new channel and new receive thread.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+HgfsTransportChannelReset(HgfsTransportChannel **channel) // IN: active channel
+{
+ Bool ret = FALSE;
+ HgfsTransportChannelClose(channel);
+ ret = HgfsTransportChannelOpen(channel);
+ LOG(8, ("Result: %s.\n", ret ? "TRUE" : "FALSE"));
+ return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportEnqueueRequest --
+ *
+ * Add the request to the gHgfsPendingRequests queue.
+ *
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsTransportEnqueueRequest(HgfsReq *req) // IN: Request to add
+{
+ ASSERT(req);
+
+ pthread_mutex_lock(&gHgfsPendingRequestsLock);
+ list_add_tail(&req->list, &gHgfsPendingRequests);
+ pthread_mutex_unlock(&gHgfsPendingRequestsLock);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportDequeueRequest --
+ *
+ * Removes the request from the gHgfsPendingRequests queue.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HgfsTransportDequeueRequest(HgfsReq *req) // IN: Request to dequeue
+{
+ ASSERT(req);
+
+ pthread_mutex_lock(&gHgfsPendingRequestsLock);
+ if (!list_empty(&req->list)) {
+ list_del_init(&req->list);
+ }
+ pthread_mutex_unlock(&gHgfsPendingRequestsLock);
+}
+
+
+/*
+ * Public function implementations.
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportProcessPacket --
+ *
+ * Helper function to process received packets, called by the channel
+ * handler thread.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+HgfsTransportProcessPacket(char *receivedPacket, //IN: received packet
+ size_t receivedSize) //IN: packet size
+{
+ struct list_head *cur, *next;
+ HgfsHandle id;
+ Bool found = FALSE;
+
+ /* Got the reply. */
+
+ ASSERT(receivedPacket != NULL && receivedSize > 0);
+ id = HgfsRequestId(receivedPacket);
+ LOG(8, ("Entered.\n"));
+ LOG(6, ("Req id: %d\n", id));
+ /*
+ * Search through gHgfsPendingRequests queue for the matching id and wake up
+ * the associated waiting process. Delete the req from the queue.
+ */
+ pthread_mutex_lock(&gHgfsPendingRequestsLock);
+ list_for_each_safe(cur, next, &gHgfsPendingRequests) {
+ HgfsReq *req;
+ req = list_entry(cur, HgfsReq, list);
+ if (req->id == id) {
+ ASSERT(req->state == HGFS_REQ_STATE_SUBMITTED);
+ HgfsCompleteReq(req, receivedPacket, receivedSize);
+ found = TRUE;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&gHgfsPendingRequestsLock);
+
+ if (!found) {
+ LOG(4, ("No matching id, dropping reply.\n"));
+ }
+ LOG(8, ("Exited.\n"));
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportBeforeExitingRecvThread --
+ *
+ * The cleanup work to do before the recv thread exits, including
+ * completing pending requests with error.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+HgfsTransportBeforeExitingRecvThread(void)
+{
+ struct list_head *cur, *next;
+
+ /* Walk through gHgfsPendingRequests queue and reply them with error. */
+ pthread_mutex_lock(&gHgfsPendingRequestsLock);
+ list_for_each_safe(cur, next, &gHgfsPendingRequests) {
+ HgfsReq *req;
+ HgfsReply reply;
+
+ req = list_entry(cur, HgfsReq, list);
+ LOG(6, ("Injecting error reply to req id: %d\n", req->id));
+ HgfsCompleteReq(req, (char *)&reply, sizeof reply);
+ }
+ pthread_mutex_unlock(&gHgfsPendingRequestsLock);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportSendRequest --
+ *
+ * Sends the request via channel communication.
+ *
+ * Results:
+ * Zero on success, non-zero error on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsTransportSendRequest(HgfsReq *req) // IN: Request to send
+{
+ int ret;
+ ASSERT(req);
+ ASSERT(req->state == HGFS_REQ_STATE_UNSENT);
+ ASSERT(req->payloadSize <= HGFS_LARGE_PACKET_MAX);
+
+ pthread_mutex_lock(&gHgfsActiveChannelLock);
+
+ /* Try opening the channel. */
+ if (NULL == gHgfsActiveChannel &&
+ !HgfsTransportChannelOpen(&gHgfsActiveChannel)) {
+ pthread_mutex_unlock(&gHgfsActiveChannelLock);
+ return -EPROTO;
+ }
+
+ ASSERT(gHgfsActiveChannel->ops.send);
+
+ HgfsTransportEnqueueRequest(req);
+
+ ret = gHgfsActiveChannel->ops.send(gHgfsActiveChannel, req);
+ if (ret < 0) {
+ LOG(4, ("Send failed, status = %d. Try reopening the channel ...\n",
+ ret));
+ if (gHgfsActiveChannel->ops.open(gHgfsActiveChannel) &&
+ HgfsTransportChannelReset(&gHgfsActiveChannel)) {
+ ret = gHgfsActiveChannel->ops.send(gHgfsActiveChannel, req);
+ }
+ }
+
+ ASSERT(req->state == HGFS_REQ_STATE_COMPLETED ||
+ req->state == HGFS_REQ_STATE_SUBMITTED ||
+ req->state == HGFS_REQ_STATE_UNSENT);
+
+ pthread_mutex_unlock(&gHgfsActiveChannelLock);
+
+ if (ret < 0) {
+ HgfsTransportDequeueRequest(req);
+ }
+
+ return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportInit --
+ *
+ * Initialize the transport.
+ *
+ * Starts the reply thread, for handling incoming packets on the
+ * connected socket.
+ *
+ * Results:
+ * Zero on success and negative one on failure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+HgfsTransportInit(void)
+{
+ int res;
+ INIT_LIST_HEAD(&gHgfsPendingRequests);
+ res = pthread_mutex_init(&gHgfsPendingRequestsLock, NULL);
+ if( res != 0) {
+ return -1;
+ }
+ res = pthread_mutex_init(&gHgfsActiveChannelLock, NULL);
+ if( res != 0) {
+ return -1;
+ }
+ gHgfsActiveChannel = NULL;
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportExit --
+ *
+ * Teardown the transport.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Cleans up everything, frees queues, closes channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+HgfsTransportExit(void)
+{
+ LOG(8, ("Entered.\n"));
+ pthread_mutex_lock(&gHgfsActiveChannelLock);
+ HgfsTransportChannelClose(&gHgfsActiveChannel);
+ pthread_mutex_unlock(&gHgfsActiveChannelLock);
+
+ ASSERT(list_empty(&gHgfsPendingRequests));
+ LOG(8, ("Exited.\n"));
+}
diff --git a/open-vm-tools/vmhgfs-fuse/transport.h b/open-vm-tools/vmhgfs-fuse/transport.h
new file mode 100644
index 00000000..f623fe18
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/transport.h
@@ -0,0 +1,63 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * transport.h --
+ */
+
+#ifndef _HGFS_DRIVER_TRANSPORT_H_
+#define _HGFS_DRIVER_TRANSPORT_H_
+
+#include "request.h"
+#include <pthread.h>
+
+/*
+ * There are the operations a channel should implement.
+ */
+struct HgfsTransportChannel;
+typedef struct HgfsTransportChannelOps {
+ Bool (*open)(struct HgfsTransportChannel *);
+ void (*close)(struct HgfsTransportChannel *);
+ int (*send)(struct HgfsTransportChannel *, HgfsReq *);
+ int (*recv)(struct HgfsTransportChannel *, char **, size_t *);
+ void (*exit)(struct HgfsTransportChannel *);
+} HgfsTransportChannelOps;
+
+typedef enum {
+ HGFS_CHANNEL_UNINITIALIZED,
+ HGFS_CHANNEL_NOTCONNECTED,
+ HGFS_CHANNEL_CONNECTED,
+} HgfsChannelStatus;
+
+typedef struct HgfsTransportChannel {
+ const char *name; /* Channel name. */
+ HgfsTransportChannelOps ops; /* Channel ops. */
+ HgfsChannelStatus status; /* Connection status. */
+ void *priv; /* Channel private data. */
+ pthread_mutex_t connLock; /* Protect _this_ struct. */
+} HgfsTransportChannel;
+
+/* Public functions (with respect to the entire module). */
+int HgfsTransportInit(void);
+void HgfsTransportExit(void);
+int HgfsTransportSendRequest(HgfsReq *req);
+void HgfsTransportProcessPacket(char *receivedPacket,
+ size_t receivedSize);
+void HgfsTransportBeforeExitingRecvThread(void);
+
+#endif // _HGFS_DRIVER_TRANSPORT_H_
diff --git a/open-vm-tools/vmhgfs-fuse/vmhgfs_version.h b/open-vm-tools/vmhgfs-fuse/vmhgfs_version.h
new file mode 100644
index 00000000..84a32456
--- /dev/null
+++ b/open-vm-tools/vmhgfs-fuse/vmhgfs_version.h
@@ -0,0 +1,32 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * vmhgfs_version.h --
+ *
+ * Version definitions for the Linux vmhgfs driver.
+ */
+
+#ifndef _VMHGFS_VERSION_H_
+#define _VMHGFS_VERSION_H_
+
+#define VMHGFS_DRIVER_VERSION 1.6.2.0
+#define VMHGFS_DRIVER_VERSION_COMMAS 1,6,2,0
+#define VMHGFS_DRIVER_VERSION_STRING "1.6.2.0"
+
+#endif /* _VMHGFS_VERSION_H_ */
diff --git a/open-vm-tools/vmware-user-suid-wrapper/wrapper.h b/open-vm-tools/vmware-user-suid-wrapper/wrapper.h
index 21dd4ab0..c021e97f 100644
--- a/open-vm-tools/vmware-user-suid-wrapper/wrapper.h
+++ b/open-vm-tools/vmware-user-suid-wrapper/wrapper.h
@@ -38,7 +38,7 @@
/*
- * XXX Document official VMware Tools releases vs. Open VM Tools and the
+ * XXX Document official VMware Tools releases vs. open-vm-tools and the
* use of the locations database in the former vs. compile-time pathing
* in the latter.
*/