]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
2009.07.22-179896 2009.07.22-179896
authorMarcelo Vanzin <mvanzin@mvanzin-dev1.eng.vmware.com>
Wed, 22 Jul 2009 18:02:33 +0000 (11:02 -0700)
committerMarcelo Vanzin <mvanzin@mvanzin-dev1.eng.vmware.com>
Wed, 22 Jul 2009 18:02:33 +0000 (11:02 -0700)
142 files changed:
open-vm-tools/ChangeLog
open-vm-tools/NEWS
open-vm-tools/configure.ac
open-vm-tools/lib/dict/dictll.c
open-vm-tools/lib/dnd/dndCommon.c
open-vm-tools/lib/dndGuest/copyPasteRpcV3.cc
open-vm-tools/lib/dndGuest/dnd.cc
open-vm-tools/lib/dndGuest/dnd.hh
open-vm-tools/lib/dndGuest/dndRpc.hh
open-vm-tools/lib/dndGuest/dndRpcV3.cc
open-vm-tools/lib/file/file.c
open-vm-tools/lib/file/fileIOPosix.c
open-vm-tools/lib/file/fileLockPosix.c
open-vm-tools/lib/file/fileLockPrimitive.c
open-vm-tools/lib/file/filePosix.c
open-vm-tools/lib/foundryMsg/foundryMsg.c
open-vm-tools/lib/ghIntegration/ghIntegration.c
open-vm-tools/lib/ghIntegration/ghIntegrationInt.h
open-vm-tools/lib/ghIntegration/ghIntegrationX11.c
open-vm-tools/lib/guestApp/guestAppPosixX11.c
open-vm-tools/lib/guestInfo/guestInfo.c
open-vm-tools/lib/guestRpc/Makefile.am
open-vm-tools/lib/guestRpc/ghiGetExecInfoHash.x [new file with mode: 0644]
open-vm-tools/lib/hgfs/cpName.c
open-vm-tools/lib/hgfs/cpNameLinux.c
open-vm-tools/lib/hgfsServer/hgfsServer.c
open-vm-tools/lib/hgfsServer/hgfsServerLinux.c
open-vm-tools/lib/image/imageUtilPng.c
open-vm-tools/lib/include/appUtil.h
open-vm-tools/lib/include/buildNumber.h
open-vm-tools/lib/include/circList.h
open-vm-tools/lib/include/config.h
open-vm-tools/lib/include/dbllnklst.h
open-vm-tools/lib/include/dndBase.h
open-vm-tools/lib/include/dndMsg.h
open-vm-tools/lib/include/escape.h
open-vm-tools/lib/include/file.h
open-vm-tools/lib/include/guestCaps.h
open-vm-tools/lib/include/guest_os.h
open-vm-tools/lib/include/hashTable.h
open-vm-tools/lib/include/hgfsProto.h
open-vm-tools/lib/include/hostinfo.h
open-vm-tools/lib/include/imageUtil.h
open-vm-tools/lib/include/imageUtilTypes.h
open-vm-tools/lib/include/loglevel_user.h
open-vm-tools/lib/include/msgid.h
open-vm-tools/lib/include/netutil.h
open-vm-tools/lib/include/rasterConv.h
open-vm-tools/lib/include/region.h
open-vm-tools/lib/include/system.h
open-vm-tools/lib/include/unityCommon.h
open-vm-tools/lib/include/unityWindowTracker.h
open-vm-tools/lib/include/util.h
open-vm-tools/lib/include/vix.h
open-vm-tools/lib/include/vixCommands.h
open-vm-tools/lib/include/vixOpenSource.h
open-vm-tools/lib/include/vm_basic_asm_x86.h
open-vm-tools/lib/include/vm_basic_defs.h
open-vm-tools/lib/include/vm_basic_types.h
open-vm-tools/lib/include/vm_device_version.h
open-vm-tools/lib/include/vm_product.h
open-vm-tools/lib/include/vm_tools_version.h
open-vm-tools/lib/include/vm_version.h
open-vm-tools/lib/include/vmtoolsApp.h
open-vm-tools/lib/include/wiper.h
open-vm-tools/lib/include/x86cpuid.h
open-vm-tools/lib/misc/dbllnklst.c
open-vm-tools/lib/misc/escape.c
open-vm-tools/lib/misc/hashTable.c
open-vm-tools/lib/misc/hostinfoPosix.c
open-vm-tools/lib/netUtil/netUtilLinux.c
open-vm-tools/lib/printer/printer.c
open-vm-tools/lib/raster/rasterConv.c
open-vm-tools/lib/region/region.c
open-vm-tools/lib/string/str.c
open-vm-tools/lib/sync/syncWaitQPosix.c
open-vm-tools/lib/system/systemLinux.c
open-vm-tools/lib/unity/unity.c
open-vm-tools/lib/unity/unityPlatform.h
open-vm-tools/lib/unity/unityPlatformX11.c
open-vm-tools/lib/unity/unityPlatformX11Window.c
open-vm-tools/lib/unity/unityX11.h
open-vm-tools/lib/unityWindowTracker/unityWindowTracker.c
open-vm-tools/lib/user/hostinfoPosix2.c
open-vm-tools/lib/user/util.c
open-vm-tools/lib/user/utilPosix.c
open-vm-tools/lib/vixTools/vixTools.c
open-vm-tools/lib/wiper/wiperPosix.c
open-vm-tools/libguestlib/Makefile.am
open-vm-tools/libguestlib/vmguestlib.pc.in [new file with mode: 0644]
open-vm-tools/libvmtools/vmtoolsConfig.c
open-vm-tools/modules/freebsd/vmhgfs/vnopscommon.c
open-vm-tools/modules/linux/dkms.conf
open-vm-tools/modules/linux/dkms.sh [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/scsi_defs.h
open-vm-tools/modules/linux/shared/compat_sock.h
open-vm-tools/modules/linux/shared/vmci_kernel_if.h
open-vm-tools/modules/linux/shared/vmci_queue_pair.h
open-vm-tools/modules/linux/vmci/vmciKernelIf.c
open-vm-tools/modules/linux/vmhgfs/bdhandler.c
open-vm-tools/modules/linux/vmhgfs/request.c
open-vm-tools/modules/linux/vmhgfs/tcp.c
open-vm-tools/modules/linux/vmxnet/vmxnet.c
open-vm-tools/modules/linux/vmxnet3/Makefile.kernel
open-vm-tools/modules/linux/vmxnet3/vmxnet3_drv.c [moved from open-vm-tools/modules/linux/vmxnet3/vmxnet3.c with 94% similarity]
open-vm-tools/modules/linux/vmxnet3/vmxnet3_int.h
open-vm-tools/modules/linux/vmxnet3/vmxnet3_shm.c [new file with mode: 0644]
open-vm-tools/modules/linux/vmxnet3/vmxnet3_shm.h [new file with mode: 0644]
open-vm-tools/modules/linux/vmxnet3/vmxnet3_shm_shared.h [new file with mode: 0644]
open-vm-tools/modules/linux/vmxnet3/vmxnet3_version.h
open-vm-tools/modules/linux/vsock/linux/af_vsock.c
open-vm-tools/modules/linux/vsock/linux/vsockAddr.c
open-vm-tools/modules/linux/vsock/linux/vsockAddr.h
open-vm-tools/modules/shared/vmxnet/net_sg.h
open-vm-tools/scripts/common/vmware-user.desktop
open-vm-tools/scripts/freebsd/suspend-vm-default
open-vm-tools/services/plugins/powerOps/powerOps.c
open-vm-tools/services/plugins/resolutionSet/resolutionInt.h
open-vm-tools/services/plugins/resolutionSet/resolutionSet.c
open-vm-tools/services/plugins/timeSync/timeSync.c
open-vm-tools/services/plugins/vmbackup/stateMachine.c
open-vm-tools/services/plugins/vmbackup/vmBackupInt.h
open-vm-tools/services/plugins/vmbackup/vmbackup_def.h
open-vm-tools/services/vmtoolsd/Makefile.am
open-vm-tools/services/vmtoolsd/mainLoop.c
open-vm-tools/services/vmtoolsd/mainPosix.c
open-vm-tools/services/vmtoolsd/pluginMgr.c
open-vm-tools/services/vmtoolsd/toolsCoreInt.h
open-vm-tools/services/vmtoolsd/toolsRpc.c
open-vm-tools/toolbox/toolbox-cmd.c
open-vm-tools/toolbox/toolboxCmdInt.h
open-vm-tools/toolbox/toolboxcmd-scripts.c
open-vm-tools/vmware-user/copyPaste.c
open-vm-tools/vmware-user/copyPasteDnDWrapper.cpp
open-vm-tools/vmware-user/copyPasteUI.cpp
open-vm-tools/vmware-user/copyPasteUI.h
open-vm-tools/vmware-user/dnd.c
open-vm-tools/vmware-user/dndUI.cpp
open-vm-tools/vmware-user/dndUI.h
open-vm-tools/vmware-user/dragDetWnd.cpp
open-vm-tools/vmware-user/dragDetWnd.h
open-vm-tools/vmware-user/vmware-user.cpp

index ef09141734c104864caaedc110ee41cacbf3a1f8..1dc113ec9164304baeb8b6305d1e82e17f21b58b 100644 (file)
@@ -1,3 +1,127 @@
+2009-07-22     Marcelo Vanzin   <mvanzin@vmware.com>
+       * Resync with internal trunk (2009.07.17)
+
+       * configure.ac: fix detection of "dot" and its usage in the doxygen config
+         file.
+
+       * configure.ac, libguestlib/Makefile.am, libguestlib/vmguestlib.pc.in:
+         install vmguestlib headers and add new pkgconfig script.
+
+       * lib/dndGuest/dnd.{cc,hh}, lib/include/dndBase.h, vmware-user/dndUI.{cpp,h}:
+         fix an issue where the DnD code would prevent drops to other windows in
+         Unity mode, instead of just intercepting drops to the desktop.
+
+       * lib/dndGuest/dnd.{cc,hh}, lib/dndGuest/dndRpc.hh, lib/dndGuest/dndRpcV3.cc,
+         lib/include/dndBase.h, vmware-user/dndUI.{cpp,h}: fix an issue where the
+         host Unity code would cause an undesired drop event.
+
+       * lib/dndGuest/dnd.{cc,hh}, lib/dndGuest/dndRpc.hh, lib/dndGuest/dndRpcV3.cc,
+         lib/include/dndBase.h: cleanup mouse simulation code, and fix an issue
+         where a drag would be canceled if the contents were dragged out of a guest
+         and then back in.
+
+       * lib/dndGuest/dndRpcV3.cc, vmware-user/copyPasteDnDWrapper.cpp,
+         vmware-user/dndUI.cpp, vmware-user/dndUI.h, vmware-user/dragDetWnd.cpp,
+         vmware-user/dragDetWnd.h: several DnD fixes; make the DnD code behave
+         more like other GTK applications (based on analysing the flow of signals
+         on a test widget), and get rid of one of the detection windows, merging
+         both the Unity and non-Unity windows. Also, some code refactoring.
+
+       * lib/ghIntegration/*, lib/guestRpc/*, lib/include/guestCaps.h,
+         lib/include/unityCommon.h: add stubs for a few new GHI functions (setting
+         window focus, tray icon updates and enhanced app info) - currently only
+         implemented on Win32.
+
+       * lib/ghIntegration/ghIntegrationX11.c: examine WM_CLASS when determining
+         which DE Tools are running in. The previous code was failing to show a
+         few entries set as "OnlyShowIn=xxx" because checking WM_NAME wasn't enough
+         to properly detect the desktop environment in certain cases.
+
+       * lib/guestApp/guestAppPosixX11.c: use gconftool-2 to detect the user's
+         browser, since gnome-open fails to open "file://" URLs which contain query
+         strings. Also, use "kde-open" when running under KDE.
+
+       * lib/guestInfo/guestInfo.c, lib/include/wiper.h, lib/wiper/wiperPosix.c:
+         allow shrinking LVM partitions.
+
+       * lib/include/appUtil.h: partial refactoring of icon retrieval code.
+
+       * lib/include/dbllnklst.h, lib/misc/dbllnklst.c: inline linked list
+         functions.
+
+       * lib/include/guest_os.h, lib/misc/hostinfoPosix.c: add a couple of
+         distros to the known distro list.
+
+       * lib/include/netutil.h, lib/netUtil/netUtilLinux.c: add Linux interface
+         name, index lookup routines.
+
+       * lib/include/system.h, lib/system/systemLinux.c,
+         services/plugins/timeSync/timeSync.c: fixes a few bugs in the backwards
+         time sync code, mostly due to unit mismatches.
+
+       * lib/include/unityWindowTracker.h, lib/unity/unity.c,
+         lib/unity/unityPlatform.h, lib/unity/unityPlatformX11Window.c,
+         lib/unityWindowTracker/unityWindowTracker.c: expose two new properties in
+         the window tracker to save an RPC to retrieve those properties.
+
+       * lib/include/vmtoolsApp.h, services/vmtoolsd/mainLoop.c,
+         services/vmtoolsd/pluginMgr.c, services/vmtoolsd/toolsCoreInt.h: add
+         support for "application providers", which allow plugins to add support to
+         new kinds of application frameworks through vmtoolsd.
+
+       * lib/unity/unityPlatformX11.c: only enable GIO channels when Unity is
+         actually active.
+
+       * lib/unity/*: cleanup old GTK1 code.
+
+       * libvmtools/vmtoolsConfig.c: don't complain if config file is empty.
+
+       * modules/linux/dkms.conf, modules/linux/dkms.sh: fix dkms.conf, and provide
+         a script to create a dkms tree from open-vm-tools.
+
+       * modules/linux/shared/vmci_queue_pair.h, modules/linux/vmci/vmciKernelIf.c:
+         remove two (now) unneeded functions.
+
+       * modules/linux/vmhgfs/*: code cleanups, properly initialize the list head,
+         and allow receives to timeout so that hibernation works.
+
+       * modules/linux/vmxnet/vmxnet.c, modules/linux/vmxnet3/vmxnet3_drv.c: fix
+         drivers for kernels 2.6.29+.
+
+       * modules/linux/vmxnet3/*: add shared memory support for faster communication
+         between user space and the device backend; this doesn't affect the regular
+         driver functionality, but is used by some VMware code not part of Tools.
+
+       * modules/linux/vsock/*: fix an issue where it was possible for users to send
+         VMCI datagrams directly to the hypervisor.
+
+       * scripts/common/vmware-user.desktop: work around a bug in KDE where desktop
+         files with "NoDisplay" fail to autostart.
+
+       * scripts/freebsd/suspend-vm-default: use netif to bring down interfaces,
+         since dhclient doesn't understand "-r" in the default install.
+
+       * services/plugins/vmbackup/*: add some new code used by enhancements being
+         done in the Win32 version of the plugin.
+
+       * services/vmtoolsd/mainPosix.c: fix running in background when executing
+         vmtoolsd while relying on PATH.
+
+       * services/vmtoolsd/Makefile.am: point to the correct plugin install
+         directory.
+
+       * toolbox/*: better command line handling in the CLI utility, plus some code
+         cleanup.
+
+       * vmware-user/copyPaste.c, vmware-user/copyPasteDnDWrapper.cpp,
+         vmware-user/copyPasteDnDWrapper.h, vmware-user/dnd.c: properly unregister
+         RPCs to avoid multiple registrations (and the ensuing ASSERT) in certain
+         cases.
+
+       * vmware-user/copyPasteUI.{cpp,h}: change way data is retrieved from the
+         clipboard, using the gtk+ clipboard wait APIs (which turn out to be more
+         reliable than the previous approach).
+
 2009-06-18     Marcelo Vanzin   <mvanzin@vmware.com>
        * Resync with internal trunk (2009.06.15)
 
index 629c793cdf7e1ae9003a42f2c90715ee23b87317..d90f591ee3357208e890ddafddd20429e274bd38 100644 (file)
@@ -1,3 +1,13 @@
+open-vm-tools 2009.07.22 changes:
+       * Better support for dkms by means of a script to help create a dkms tree.
+
+       * "make install" now also installs header files for public libraries, plus
+       a few fixes to incorrect install behavior.
+
+       * Lots of improvements to the new DnD code.
+
+       * This will be the last release with support for Linux kernels < 2.6.9.
+
 open-vm-tools 2009.06.18 changes:
        * Mostly a bug fix release.
 
index 0abc463bf2d453f87b5f95e4d7b508aaee908e64..720b8b3fd5a8dc4fced4c025858b6936aed224dc 100644 (file)
 ### Initialization
 ###
 
-TOOLS_VERSION="2009.06.18"
+TOOLS_VERSION="2009.07.22"
 AC_INIT(
    [open-vm-tools],
-   [2009.06.18],
+   [2009.07.22],
    [open-vm-tools-devel@lists.sourceforge.net])
 
 # In order to make this configure script auto-detect situations where
@@ -887,16 +887,15 @@ if test "$enable_docs" = "yes"; then
    if test "$have_doxygen" = "no"; then
       AC_MSG_WARN([doxygen not found; API documentation will not be generated.])
    else
-      AC_CHECK_PROG([HAVE_DOT],
-                    [dot],
-                    [yes],
-                    [no])
-      if test "$HAVE_DOT" = "yes"; then
-         DOT=dot
+      AC_PATH_PROG([DOT], [dot], [])
+      if test "$DOT" = ""; then
+         HAVE_DOT=NO
       else
-         DOT=
+         DOT=`dirname $DOT`
+         HAVE_DOT=YES
       fi
       AC_SUBST([DOT])
+      AC_SUBST([HAVE_DOT])
 
       AC_PATH_PROG([MSCGEN],
                    [mscgen],
@@ -1226,6 +1225,7 @@ AC_CONFIG_FILES([                      \
    checkvm/Makefile                    \
    rpctool/Makefile                    \
    libguestlib/Makefile                \
+   libguestlib/vmguestlib.pc           \
    libvmtools/Makefile                 \
    xferlogs/Makefile                   \
    modules/Makefile                    \
index a1e397bcb8e4e43c8450a01ae2b4daad257d4b97..0733b2cdd03099cf1de7a5e2c868b504550687b8 100644 (file)
@@ -97,17 +97,20 @@ XXX document the escaping/unescaping process: rationale for which chars we escap
 
 
 /*
-XXX document the dict format:
-
-     whitespaces <name> whitespaces '=' whitespaces <value> whitespaces comment
-  or
-     whitespaces <name> whitespaces '=' whitespaces '"' <value> '"' whitespaces comment
-
-  where:
-
-  . <name> does not contain any whitespace or = or pound
-  . <value> does not contain any double-quote or pound
-*/
+ * The dictionary line format:
+ *
+ *    <ws> <name> <ws> = <ws> <value> <ws> <comment>
+ * or
+ *    <ws> <name> <ws> = <ws> " <quoted-value> " <ws> <comment>
+ *
+ * where
+ *    <name> does not contain any whitespace or = or #
+ *    <value> does not contain any double-quote or #
+ *    <quoted-value> does not contain any double-quote
+ *    <comment> begins with # and ends at the end of the line
+ *    <ws> is a sequence spaces and/or tabs
+ *    <comment> and <ws> are optional
+ */
 
 
 /*
@@ -390,15 +393,15 @@ DictLL_MarshalLine(DynBuf *output,    // IN/OUT: output buffer
 
    if (name) {
       /*
-       * Double quote, pound, pipe, 0x7F, and all control characters but
+       * Double quote, pipe, 0x7F, and all control characters but
        * tab --hpreg
-       * XXX Why 7F? Why not also 84 and 85 and 90 which do funny things in a
-       *     xterm?
+       * 0x80 to 0xff are unescaped so characters in encodings
+       * like UTF-8 will be displayed normally.
        */
       static int const toEscape[] = {
          1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-         0, 0, 1, 1, 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, 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,
index 5c7789c556e8b20a12dc7e9491d0e4bae3d09796..9ee37d71eb8849bce2bd8121c7eb43f601963745 100644 (file)
@@ -342,6 +342,7 @@ DnDPrependFileRoot(ConstUnicode fileRoot,  // IN    : file root to append
     * 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');
@@ -352,10 +353,11 @@ DnDPrependFileRoot(ConstUnicode fileRoot,  // IN    : file root to append
       int escapedLen;
 
       if (len < 0) {
-         Log("DnDPrependFileRoot: error getting next component\n");
+         Log("%s: error getting next component\n", __FUNCTION__);
          if (!firstPass) {
             free(newData);
          }
+
          return FALSE;
       }
 
@@ -363,6 +365,7 @@ DnDPrependFileRoot(ConstUnicode fileRoot,  // IN    : file root to append
        * 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 (0 == escapedLen) {
          newDataLen += rootLen + len + 1;
@@ -474,13 +477,14 @@ DnD_LegacyConvertToCPName(const char *nameIn,   // IN:  Buffer to convert
    memcpy(fullName + partialNameLen + partialNameSuffixLen, nameIn, nameSize);
    fullName[fullNameSize] = '\0';
 
-   LOG(4, ("DnD_LegacyConvertToCPName: generated name is \"%s\"\n", fullName));
+   LOG(4, ("%s: generated name is \"%s\"\n", __FUNCTION__, fullName));
 
    /*
     * CPName_ConvertTo implementation is performed here without calling any
     * CPName_ functions.  This is safer since those functions might change, but
     * the legacy behavior we are special casing here will not.
     */
+
    {
       char const *winNameIn = fullName;
       char const *origOut = bufOut;
@@ -497,6 +501,7 @@ DnD_LegacyConvertToCPName(const char *nameIn,   // IN:  Buffer to convert
        * Copy the string to the output buf, converting all path separators into
        * '\0' and ignoring the specified characters.
        */
+
       for (; *winNameIn != '\0' && bufOut < endOut; winNameIn++) {
          if (ignores) {
             char *currIgnore = ignores;
@@ -526,6 +531,7 @@ DnD_LegacyConvertToCPName(const char *nameIn,   // IN:  Buffer to convert
        * When we get rid of NUL termination here, this test should
        * also change to "if (*winNameIn != '\0')".
        */
+
       if (bufOut == endOut) {
          result = -1;
          goto out;
@@ -541,13 +547,18 @@ DnD_LegacyConvertToCPName(const char *nameIn,   // IN:  Buffer to convert
          result--;
       }
 
-      /* Make exception and call CPName_Print() here, since it's only for logging */
-      LOG(4, ("DnD_LegacyConvertToCPName: CPName is \"%s\"\n",
+      /*
+       * Make exception and call CPName_Print() here, since it's only for
+       * logging
+       */
+
+      LOG(4, ("%s: CPName is \"%s\"\n", __FUNCTION__, 
               CPName_Print(origOut, result)));
    }
 
 out:
    free(fullName);
+
    return result;
 }
 
index d413aa47c8ff77fcfc344812fcccccf7ea866ec5..1d10b4bc163a694a5ff127761acb50a02b505ccc 100644 (file)
@@ -233,6 +233,33 @@ CopyPasteRpcV3::OnRecvMsg(const uint8 *data, // IN
    switch (DnDMsg_GetCmd(&msg)) {
    case CP_GH_GET_CLIPBOARD:
       ghGetClipboardChanged.emit();
+#if defined (DND_TRANSPORT_TEST)
+      /* Sending 60 packets to host side to test transport. */
+      for (uint32 i = 1; i < 60; i++) {
+         DnDMsg msg;
+         DynBuf buf;
+
+         DnDMsg_Init(&msg);
+         DynBuf_Init(&buf);
+
+         DnDMsg_SetCmd(&msg, CP_GH_TRANSPORT_TEST);
+         if (!DnDMsg_AppendArg(&msg, &i, sizeof i)) {
+            Debug("%s: DnDMsg_AppendData failed.\n", __FUNCTION__);
+            goto error;
+         }
+
+         if (!DnDMsg_Serialize(&msg, &buf)) {
+            Debug("%s: DnDMsg_Serialize failed.\n", __FUNCTION__);
+            goto error;
+         }
+
+         mTransport->SendMsg((uint8 *)DynBuf_Get(&buf), DynBuf_GetSize(&buf));
+
+      error:
+         DynBuf_Destroy(&buf);
+         DnDMsg_Destroy(&msg);
+      }
+#endif
       break;
    case CP_HG_SET_CLIPBOARD:
    {
index a837a20c3231f67318c6652c1d5766c2350e3287..c4dc8c1649cd0d09ba4a1b6c3d56efc595150dd0 100644 (file)
@@ -34,8 +34,9 @@ extern "C" {
    #include "eventManager.h"
 }
 
-#define UNGRAB_TIMEOUT 50     // 0.5 s
-#define HIDE_DET_WND_TIMER 50 // 0.5s
+#define UNGRAB_TIMEOUT 50        // 0.5 s
+#define UNITY_DND_DET_TIMEOUT 50 // 0.5 s
+#define HIDE_DET_WND_TIMER 50    // 0.5s
 
 
 /*
@@ -55,7 +56,7 @@ extern "C" {
  */
 
 static Bool
-DnDUngrabTimeout(void *clientData)      // IN
+DnDUngrabTimeout(void *clientData) // IN
 {
    ASSERT(clientData);
    DnD *dnd = (DnD *)clientData;
@@ -64,6 +65,32 @@ DnDUngrabTimeout(void *clientData)      // IN
 }
 
 
+/*
+ *---------------------------------------------------------------------
+ *
+ * DnDUnityDetTimeout --
+ *
+ *      UnityDnDDetTimeout callback for GH DnD.
+ *
+ * Results:
+ *      Always TRUE.
+ *
+ * Side effects:
+ *      None.
+ *
+ *---------------------------------------------------------------------
+ */
+
+static Bool
+DnDUnityDetTimeout(void *clientData)      // IN
+{
+   ASSERT(clientData);
+   DnD *dnd = (DnD *)clientData;
+   dnd->UnityDnDDetTimeout();
+   return TRUE;
+}
+
+
 /*
  *---------------------------------------------------------------------
  *
@@ -114,6 +141,7 @@ DnD::DnD(DblLnkLst_Links *eventQueue) // IN
      mDnDAllowed(false),
      mStagingDir(""),
      mUngrabTimeout(NULL),
+     mUnityDnDDetTimeout(NULL),
      mHideDetWndTimer(NULL),
      mEventQueue(eventQueue)
 {
@@ -153,6 +181,10 @@ DnD::~DnD(void)
       EventManager_Remove(mUngrabTimeout);
       mUngrabTimeout = NULL;
    }
+   if (mUnityDnDDetTimeout) {
+      EventManager_Remove(mUnityDnDDetTimeout);
+      mUnityDnDDetTimeout = NULL;
+   }
 }
 
 
@@ -207,6 +239,10 @@ DnD::VmxDnDVersionChanged(struct RpcIn *rpcIn, // IN
          sigc::mem_fun(this, &DnD::OnGHUpdateUnityDetWnd));
       mRpc->ghQueryPendingDragChanged.connect(
          sigc::mem_fun(this, &DnD::OnGHQueryPendingDrag));
+      mRpc->moveDetWndToMousePos.connect(
+         sigc::mem_fun(this, &DnD::OnMoveDetWndToMousePos));
+      mRpc->ghPrivateDropChanged.connect(
+         sigc::mem_fun(this, &DnD::OnGHPrivateDrop));
       mRpc->ghCancelChanged.connect(
          sigc::mem_fun(this, &DnD::OnGHCancel));
       mRpc->hgDragEnterChanged.connect(
@@ -617,15 +653,46 @@ DnD::OnGHUpdateUnityDetWnd(bool bShow,        // IN
        * this window to accept drop in cancel case.
        */
       UpdateDetWnd(bShow, 1, 1);
+      if (mUnityDnDDetTimeout) {
+         EventManager_Remove(mUnityDnDDetTimeout);
+         mUnityDnDDetTimeout = NULL;
+      }
+      mUnityDnDDetTimeout = EventManager_Add(mEventQueue, UNITY_DND_DET_TIMEOUT,
+                                             DnDUnityDetTimeout, this);
    }
 
    /* Show/hide the full screent detection window. */
-   updateUnityDetWndChanged.emit(bShow, unityWndId);
+   updateUnityDetWndChanged.emit(bShow, unityWndId, false);
    Debug("%s: updating Unity detection window, bShow %d, id %u\n",
          __FUNCTION__, bShow, unityWndId);
 }
 
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * DnD::UnityDnDDetTimeout --
+ *
+ *      Can not detect pending GH DnD within UNITY_DND_DET_TIMEOUT, put
+ *      the full screen detection window to bottom most.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+DnD::UnityDnDDetTimeout(void)
+{
+   mUnityDnDDetTimeout = NULL;
+   updateUnityDetWndChanged.emit(true, 0, true);
+}
+
+
 /*
  *----------------------------------------------------------------------
  *
@@ -768,6 +835,60 @@ DnD::DragEnter(const CPClipboard *clip)
 }
 
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * DnD::OnMoveDetWndToMousePos --
+ *
+ *      Move detection windows to current cursor position to prevent
+ *      unexpected drop.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+DnD::OnMoveDetWndToMousePos(void)
+{
+   Debug("%s: entering\n", __FUNCTION__);
+   moveDetWndToMousePos.emit();
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DnD::OnGHPrivateDrop --
+ *
+ *      User started a GH DnD, dragged back to VM and dropped. In guest
+ *      side we should simulate the drop, hide detection window and reset
+ *      the state machine.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+DnD::OnGHPrivateDrop(int32 x, // IN
+                     int32 y) // IN
+{
+   targetPrivateDropChanged.emit(x, y);
+   updateDetWndChanged.emit(false, 0, 0);
+   mState = DNDSTATE_READY;
+   Debug("%s: state changed to READY\n", __FUNCTION__);
+}
+
+
 /*
  *----------------------------------------------------------------------
  *
index b87f7c6f4d201c536e0ba3d47c7cea35c40b5789..326e5c0891793bf10e8bdec12d20751fdd79df22 100644 (file)
@@ -65,6 +65,7 @@ class DnD
       void SetDnDAllowed(bool isDnDAllowed)
          { mDnDAllowed = isDnDAllowed; }
       void UngrabTimeout(void);
+      void UnityDnDDetTimeout(void);
       void ResetDnD(void);
       void HGDragStartDone(void);
       void OnUpdateMouse(int32 x, int32 y);
@@ -75,6 +76,7 @@ class DnD
       /* Callbacks from rpc. */
       void OnGHUpdateUnityDetWnd(bool bShow, uint32 unityWndId);
       void OnGHQueryPendingDrag(int x, int y);
+      void OnGHPrivateDrop(int32 x, int32 y);
       void OnGHCancel(void);
       void OnHGDragEnter(const CPClipboard *clip);
       void OnHGDragStart(void);
@@ -82,6 +84,7 @@ class DnD
       void OnHGDrop(void);
       void OnHGFileCopyDone(bool cancel,
                             std::vector<uint8> stagingDir);
+      void OnMoveDetWndToMousePos(void);
 
       std::string SetupDestDir(const std::string &destDir);
 
@@ -90,6 +93,7 @@ class DnD
       bool mDnDAllowed;
       std::string mStagingDir;
       Event *mUngrabTimeout;
+      Event *mUnityDnDDetTimeout;
       Event *mHideDetWndTimer;
       DblLnkLst_Links *mEventQueue;
 };
index 2712c1022b407b24166aa03dac273c226911992a..f8adbaf2667e1bc7319a71ce95e809083584bb83 100644 (file)
@@ -41,6 +41,7 @@ class DnDRpc
       /* sigc signals for callback. */
       sigc::signal<void, bool, uint32> ghUpdateUnityDetWndChanged;
       sigc::signal<void, int, int> ghQueryPendingDragChanged;
+      sigc::signal<void, int32, int32>ghPrivateDropChanged;
       sigc::signal<void> ghCancelChanged;
       sigc::signal<void, const CPClipboard*> hgDragEnterChanged;
       sigc::signal<void> hgDragStartChanged;
@@ -48,6 +49,7 @@ class DnDRpc
       sigc::signal<void> hgDropChanged;
       sigc::signal<void, bool, const std::vector<uint8> > hgFileCopyDoneChanged;
       sigc::signal<void, int32, int32> updateMouseChanged;
+      sigc::signal<void> moveDetWndToMousePos;
 
       /* GH DnD. */
       virtual bool GHDragEnter(const CPClipboard *clip) = 0;
@@ -61,6 +63,7 @@ class DnDRpc
 
    protected:
       uint32 mHostMinorVersion;
+      uint32 mGuestMinorVersion;
 };
 
 #endif // DND_RPC_HH
index 40c82cbe4f4ba112d32f8d48d422476e5dc933bf..9e437a9d1cb24e55f9d27f6bf3afac6095dcb8e6 100644 (file)
@@ -54,11 +54,10 @@ DnDRpcV3::DnDRpcV3(struct RpcIn *rpcIn) // IN
    mTransport->recvMsgChanged.connect(sigc::mem_fun(this, &DnDRpcV3::OnRecvMsg));
 
    mHostMinorVersion = 0;
+   mGuestMinorVersion = 0;
    /* Tell host that current DnD version in guest side is 3.1. */
-   /* XXX Windows only for now. Linux implementation will be in shortly. */
-#if defined (_WIN32)
-   UpdateGuestVersion(3, 1);
-#endif // _WIN32
+   mGuestMinorVersion = 1;
+   UpdateGuestVersion(3, mGuestMinorVersion);
 }
 
 
@@ -557,6 +556,34 @@ DnDRpcV3::OnRecvMsg(const uint8 *data, // IN
          break;
       }
       hgDragEnterChanged.emit(&clip);
+
+#if defined (DND_TRANSPORT_TEST)
+      /* Sending 60 packets to host side to test transport. */
+      for (uint32 i = 1; i < 60; i++) {
+         DnDMsg msg;
+         DynBuf buf;
+
+         DnDMsg_Init(&msg);
+         DynBuf_Init(&buf);
+
+         DnDMsg_SetCmd(&msg, DND_GH_TRANSPORT_TEST);
+         if (!DnDMsg_AppendArg(&msg, &i, sizeof i)) {
+            Debug("%s: DnDMsg_AppendData failed.\n", __FUNCTION__);
+            goto error;
+         }
+
+         if (!DnDMsg_Serialize(&msg, &buf)) {
+            Debug("%s: DnDMsg_Serialize failed.\n", __FUNCTION__);
+            goto error;
+         }
+
+         mTransport->SendMsg((uint8 *)DynBuf_Get(&buf), DynBuf_GetSize(&buf));
+
+      error:
+         DynBuf_Destroy(&buf);
+         DnDMsg_Destroy(&msg);
+      }
+#endif
       break;
    }
    case DND_HG_DRAG_START:
@@ -614,6 +641,33 @@ DnDRpcV3::OnRecvMsg(const uint8 *data, // IN
       updateMouseChanged.emit(x, y);
       break;
    }
+   case  DND_GH_PRIVATE_DROP:
+   {
+      int32 x = 0;
+      int32 y = 0;
+
+      buf = DnDMsg_GetArg(&msg, 0);
+      if (DynBuf_GetSize(buf) == sizeof(int32)) {
+         memcpy(&x, (const char *)DynBuf_Get(buf), sizeof(int32));
+      } else {
+         break;
+      }
+
+      buf = DnDMsg_GetArg(&msg, 1);
+      if (DynBuf_GetSize(buf) == sizeof(int32)) {
+         memcpy(&y, (const char *)DynBuf_Get(buf), sizeof(int32));
+      } else {
+         break;
+      }
+
+      ghPrivateDropChanged.emit(x, y);
+      break;
+   }
+   case  DND_MOVE_DET_WND_TO_MOUSE_POS:
+   {
+      moveDetWndToMousePos.emit();
+      break;
+   }
    case DND_UPDATE_HOST_VERSION:
    {
       uint32 major = 0;
@@ -635,6 +689,7 @@ DnDRpcV3::OnRecvMsg(const uint8 *data, // IN
       }
       Debug("%s: got host DnD version %d.%d.\n",
             __FUNCTION__, major, mHostMinorVersion);
+      UpdateGuestVersion(3, mGuestMinorVersion);
       break;
    }
    default:
index 9ad6e8636a0035ab34d30d25c115d04e3f1af871..10833932e5a1e333d6bd7e2ffac92af2f9f31360 100644 (file)
@@ -30,6 +30,7 @@
 #include "safetime.h"
 #if defined(_WIN32)
 #include <io.h>
+#define S_IXUSR    0100
 #else
 #include <unistd.h>
 #endif
@@ -148,6 +149,45 @@ File_IsDirectory(ConstUnicode pathName)  // IN:
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * File_GetFilePermissions --
+ *
+ *     Return the read / write / execute permissions of a file.
+ *
+ * Results:
+ *     TRUE if success, FALSE otherwise.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+File_GetFilePermissions(ConstUnicode pathName,  // IN:
+                        int *mode)              // OUT: file mode
+{
+   FileData fileData;
+
+   ASSERT(mode);
+   if (FileAttributes(pathName, &fileData) != 0) {
+      return FALSE;
+   }
+   *mode = fileData.fileMode;
+#ifdef _WIN32
+      /*
+       *  On Win32 implementation of FileAttributes does not return execution bit.
+       */
+      if (FileIO_Access(pathName, FILEIO_ACCESS_EXEC) == FILEIO_SUCCESS) {
+         *mode |= S_IXUSR;
+      }
+#endif
+   return TRUE;
+}
+
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1674,6 +1714,79 @@ File_SupportsLargeFiles(ConstUnicode pathName)  // IN:
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * File_MapPathPrefix --
+ *
+ *      Given a path and a newPrefix -> oldPrefix mapping, transform
+ *      oldPath according to the mapping.
+ *
+ * Results:
+ *      The new path, or NULL if there is no mapping.
+ *
+ * Side effects:
+ *      The returned string is allocated, free it.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char *
+File_MapPathPrefix(const char *oldPath,               // IN
+                   const char **oldPrefixes,          // IN
+                   const char **newPrefixes,          // IN
+                   size_t numPrefixes)                // IN
+{
+   int i;
+   size_t oldPathLen = strlen(oldPath);
+
+   for (i = 0; i < numPrefixes; i++) {
+      char *newPath;
+      char *oldPrefix;
+      char *newPrefix;
+      size_t oldPrefixLen;
+
+      oldPrefix = File_StripSlashes(oldPrefixes[i]);
+      newPrefix = File_StripSlashes(newPrefixes[i]);
+      oldPrefixLen = strlen(oldPrefix);
+
+      /*
+       * If the prefix matches on a DIRSEPS boundary, or the prefix is the
+       * whole string, replace it.
+       * If we don't insist on matching a whole directory name, we could
+       * mess things of if one directory is a substring of another.
+       */
+
+      if (oldPathLen >= oldPrefixLen &&
+          memcmp(oldPath, oldPrefix, oldPrefixLen) == 0
+          && (strchr(VALID_DIRSEPS, oldPath[oldPrefixLen]) ||
+              oldPath[oldPrefixLen] == '\0')) {
+         size_t newPrefixLen = strlen(newPrefix);
+         size_t newPathLen = (oldPathLen - oldPrefixLen) + newPrefixLen;
+
+         ASSERT(newPathLen > 0);
+         ASSERT(oldPathLen >= oldPrefixLen);
+
+         newPath = Util_SafeMalloc((newPathLen + 1) * sizeof(char));
+         memcpy(newPath, newPrefix, newPrefixLen);
+         memcpy(newPath + newPrefixLen, oldPath + oldPrefixLen,
+                oldPathLen - oldPrefixLen + 1);
+         /*
+          * It should only match once.  Weird self-referencing mappings
+          * aren't allowed.
+          */
+         free(oldPrefix);
+         free(newPrefix);
+         return newPath;
+      }
+      free(oldPrefix);
+      free(newPrefix);
+   }
+
+   return NULL;
+}
+
+
 #if !defined(N_PLAT_NLM)
 /*
  *----------------------------------------------------------------------------
index 7279b99c45094757c7ec558b22689fd6e33a2c3b..d07a8c5b8de4019b9cf396ae284284eb2d56b00e 100644 (file)
 #define XATTR_BACKUP_REENABLED "com.vmware.backupReenabled"
 #endif
 
+/* 
+ * fallocate() is only supported since the glibc-2.8 and
+ * linux kernel-2.6.23.Presently the glibc in our toolchain is 2.3 
+ */
+#ifdef __linux__
+   #ifndef SYS_fallocate 
+      #ifdef __i386__
+         #define SYS_fallocate 324   
+      #elif __x86_64__ 
+         #define SYS_fallocate 285 
+      #endif
+   #endif
+   #ifndef FALLOC_FL_KEEP_SIZE 
+       #define FALLOC_FL_KEEP_SIZE 1
+   #endif      
+#endif
+
 static const unsigned int FileIO_SeekOrigins[] = {
    SEEK_SET,
    SEEK_CUR,
@@ -1296,6 +1313,7 @@ FileIOCoalesce(struct iovec *inVec,     // IN:  Vector to coalesce from
                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;
@@ -1324,7 +1342,7 @@ FileIOCoalesce(struct iovec *inVec,     // IN:  Vector to coalesce from
    // XXX: Wouldn't it be nice if we could log from here!
    //LOG(5, ("FILE: Coalescing %s of %d elements and %d size\n",
    //        isWrite ? "write" : "read", inCount, inTotalSize));
-   if (filePosixOptions.aligned) {
+   if (filePosixOptions.aligned || flags & FILEIO_OPEN_UNBUFFERED) {
       cBuf = Aligned_Malloc(sizeof(uint8) * inTotalSize);
    } else {
       cBuf = Util_SafeMalloc(sizeof(uint8) * inTotalSize);
@@ -1366,7 +1384,8 @@ 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)
+                 Bool isWrite,          // IN: decoalesce for writing (or reading)
+                 int flags)             // IN: fileIO open flags
 {
    ASSERT(coVec);
    ASSERT(origVec);
@@ -1378,7 +1397,7 @@ FileIODecoalesce(struct iovec *coVec,   // IN: Coalesced (1-entry) vector
       IOV_WriteBufToIov(coVec->iov_base, actualSize, origVec, origVecCount);
    }
 
-   if (filePosixOptions.aligned) {
+   if (filePosixOptions.aligned || flags & FILEIO_OPEN_UNBUFFERED) {
       Aligned_Free(coVec->iov_base);
    } else {
       free(coVec->iov_base);
@@ -1426,7 +1445,8 @@ FileIO_Readv(FileIODescriptor *fd,      // IN
 
    ASSERT(fd);
 
-   didCoalesce = FileIOCoalesce(v, numEntries, totalSize, FALSE, FALSE, &coV);
+   didCoalesce = FileIOCoalesce(v, numEntries, totalSize, FALSE,
+                                FALSE, fd->flags, &coV);
 
    STAT_INST_INC(fd->stats, NumReadvs);
    STAT_INST_INC_BY(fd->stats, BytesReadv, totalSize);
@@ -1491,7 +1511,7 @@ FileIO_Readv(FileIODescriptor *fd,      // IN
    }
 
    if (didCoalesce) {
-      FileIODecoalesce(&coV, v, numEntries, bytesRead, FALSE);
+      FileIODecoalesce(&coV, v, numEntries, bytesRead, FALSE, fd->flags);
    }
 
    if (actual) {
@@ -1541,7 +1561,8 @@ FileIO_Writev(FileIODescriptor *fd,     // IN
 
    ASSERT(fd);
 
-   didCoalesce = FileIOCoalesce(v, numEntries, totalSize, TRUE, FALSE, &coV);
+   didCoalesce = FileIOCoalesce(v, numEntries, totalSize, TRUE,
+                                FALSE, fd->flags, &coV);
 
    STAT_INST_INC(fd->stats, NumWritevs);
    STAT_INST_INC_BY(fd->stats, BytesWritev, totalSize);
@@ -1589,7 +1610,7 @@ FileIO_Writev(FileIODescriptor *fd,     // IN
    }
 
    if (didCoalesce) {
-      FileIODecoalesce(&coV, v, numEntries, bytesWritten, TRUE);
+      FileIODecoalesce(&coV, v, numEntries, bytesWritten, TRUE, fd->flags);
    }
 
    if (actual) {
@@ -1641,8 +1662,7 @@ FileIO_Preadv(FileIODescriptor *fd,    // IN: File descriptor
    ASSERT_NOT_IMPLEMENTED(totalSize < 0x80000000);
 
    didCoalesce = FileIOCoalesce(entries, numEntries, totalSize, FALSE,
-                                TRUE /* force coalescing */,
-                                &coV);
+                                TRUE /* force coalescing */, fd->flags, &coV);
 
    count = didCoalesce ? 1 : numEntries;
    vPtr = didCoalesce ? &coV : entries;
@@ -1695,7 +1715,7 @@ FileIO_Preadv(FileIODescriptor *fd,    // IN: File descriptor
 
 exit:
    if (didCoalesce) {
-      FileIODecoalesce(&coV, entries, numEntries, sum, FALSE);
+      FileIODecoalesce(&coV, entries, numEntries, sum, FALSE, fd->flags);
    }
 
    return fret;
@@ -1742,8 +1762,7 @@ FileIO_Pwritev(FileIODescriptor *fd,   // IN: File descriptor
    ASSERT_NOT_IMPLEMENTED(totalSize < 0x80000000);
 
    didCoalesce = FileIOCoalesce(entries, numEntries, totalSize, TRUE,
-                                TRUE /* force coalescing */,
-                                &coV);
+                                TRUE /* force coalescing */, fd->flags, &coV);
 
    count = didCoalesce ? 1 : numEntries;
    vPtr = didCoalesce ? &coV : entries;
@@ -1800,7 +1819,7 @@ FileIO_Pwritev(FileIODescriptor *fd,   // IN: File descriptor
    fret = FILEIO_SUCCESS;
 exit:
    if (didCoalesce) {
-      FileIODecoalesce(&coV, entries, numEntries, sum, TRUE);
+      FileIODecoalesce(&coV, entries, numEntries, sum, TRUE, fd->flags);
    }
 
    return fret;
@@ -1892,26 +1911,36 @@ Bool
 FileIO_SetAllocSize(const FileIODescriptor *fd,  // IN
                     uint64 size)                 // IN
 {
+
+#if defined(__APPLE__) || defined(__linux__)
+   uint64 curSize;
+   uint64 preallocLen;
 #ifdef __APPLE__
    fstore_t prealloc;
-   uint64 curSize;
+#endif
 
    curSize = FileIO_GetAllocSize(fd);
-
    if (curSize > size) {
       errno = EINVAL;
       return FALSE;
-   }
+   }   
+   preallocLen = size - curSize;
 
+#ifdef __APPLE__
    prealloc.fst_flags = 0;
    prealloc.fst_posmode = F_PEOFPOSMODE;
    prealloc.fst_offset = 0;
-   prealloc.fst_length = size - curSize;
+   prealloc.fst_length = preallocLen;
    prealloc.fst_bytesalloc = 0;
 
    return fcntl(fd->posix, F_PREALLOCATE, &prealloc) != -1;
+#elif __linux__
+   return syscall(SYS_fallocate, fd->posix, FALLOC_FL_KEEP_SIZE, 
+                 curSize, preallocLen) == 0;
+#endif
+
 #else
-   errno = EINVAL;
+   errno = ENOSYS;
    return FALSE;
 #endif
 }
index 7fae809bad8c9cf2d04db102ed52784895aa3d1c..c2a2ffa2f1036bc4c10857d130445278ddd6a599 100644 (file)
@@ -379,7 +379,7 @@ GetLockFileValues(const char *lockFileName, // IN:
 /*
  *----------------------------------------------------------------------
  *
- * IsValidProcess --
+ * FileLockIsValidProcess --
  *
  *      Determine if the process, via its pid, is valid (alive).
  *
@@ -394,7 +394,7 @@ GetLockFileValues(const char *lockFileName, // IN:
  */
 
 static Bool
-IsValidProcess(int pid)       // IN:
+FileLockIsValidProcess(int pid)  // IN:
 {
    uid_t uid;
    int err;
@@ -432,7 +432,7 @@ IsValidProcess(int pid)       // IN:
 /*
  *----------------------------------------------------------------------
  *
- * CreateLockFile --
+ * FileLockCreateLockFile --
  *
  *      Create a new lock file, either via a O_EXCL creat() call or
  *      through the linking method.
@@ -449,9 +449,9 @@ IsValidProcess(int pid)       // IN:
  */
 
 static int
-CreateLockFile(const char *lockFileName, // IN:
-               const char *lockFileLink, // IN:
-               const char *uniqueID)     // IN:
+FileLockCreateLockFile(const char *lockFileName,  // IN:
+                       const char *lockFileLink,  // IN:
+                       const char *uniqueID)      // IN:
 {
    int  err;
    int  lockFD;
@@ -527,6 +527,7 @@ exit:
       }
 
    }
+
    return status;
 }
 
@@ -572,14 +573,14 @@ FileLock_LockDevice(const char *deviceName)   // IN:
                                    deviceName, FileLockGetPid());
 
    LOG(1, ("Requesting lock %s (temp = %s).\n", lockFileName,
-       lockFileLink));
+           lockFileLink));
 
    hostID = FileLockGetMachineID();
    Str_Sprintf(uniqueID, sizeof uniqueID, "%d %s\n",
                FileLockGetPid(), hostID);
 
-   while ((status = CreateLockFile(lockFileName, lockFileLink,
-                                   uniqueID)) == 0) {
+   while ((status = FileLockCreateLockFile(lockFileName, lockFileLink,
+                                           uniqueID)) == 0) {
       int  pid;
       char fileID[1000];
 
@@ -602,17 +603,17 @@ FileLock_LockDevice(const char *deviceName)   // IN:
       }
 
       if (strcmp(hostID, fileID) != 0) {
-         // Lock was acquired by a different host.
+         /* Lock was acquired by a different host. */
          status = 0;
          goto exit;
       }
 
-      if (IsValidProcess(pid)) {
+      if (FileLockIsValidProcess(pid)) {
          status = 0;
          goto exit;
       }
 
-      // stale lock
+      /* stale lock */
      if (!RemoveStaleLockFile(lockFileName)) {
          status = -1;
          goto exit;
@@ -872,7 +873,7 @@ FileLockValidOwner(const char *executionID, // IN:
       return TRUE;
    }
 
-   if (!IsValidProcess(pid)) {
+   if (!FileLockIsValidProcess(pid)) {
       return FALSE;
    }
 
@@ -933,7 +934,7 @@ FileLockOpenFile(ConstUnicode pathName,        // IN:
 
    *handle = PosixFileOpener(pathName, flags, 0644);
 
-   return *handle == -1 ? errno : 0;
+   return (*handle == -1) ? errno : 0;
 }
 
 
@@ -957,7 +958,7 @@ FileLockOpenFile(ConstUnicode pathName,        // IN:
 int
 FileLockCloseFile(FILELOCK_FILE_HANDLE handle) // IN:
 {
-   return close(handle) == -1 ? errno : 0;
+   return (close(handle) == -1) ? errno : 0;
 }
 
 
index 75c42e2783421dfb810e8da407f853ce4cddb061..64b475b105b8ee8d7fa19010043bafe4a7853a29 100644 (file)
@@ -95,8 +95,8 @@ typedef struct parse_table
  */
 
 static int
-Sleeper(LockValues *myValues, // IN/OUT:
-        uint32 *loopCount)    // IN/OUT:
+Sleeper(LockValues *myValues,  // IN/OUT:
+        uint32 *loopCount)     // IN/OUT:
 {
    uint32 msecSleepTime;
 
@@ -266,11 +266,11 @@ FileLockParseArgs(char *argv[],       // IN:
 #define FL_MAX_ARGS 16
 
 int
-FileLockMemberValues(ConstUnicode lockDir,     // IN:
-                     ConstUnicode fileName,    // IN:
-                     char *buffer,             // OUT:
-                     uint32 requiredSize,      // IN:
-                     LockValues *memberValues) // OUT:
+FileLockMemberValues(ConstUnicode lockDir,      // IN:
+                     ConstUnicode fileName,     // IN:
+                     char *buffer,              // OUT:
+                     uint32 requiredSize,       // IN:
+                     LockValues *memberValues)  // OUT:
 {
    uint32 argc = 0;
    FILELOCK_FILE_HANDLE handle;
@@ -465,7 +465,7 @@ bail:
  */
 
 Bool
-FileLockValidName(ConstUnicode fileName) // IN:
+FileLockValidName(ConstUnicode fileName)  // IN:
 {
    uint32 i;
 
@@ -886,7 +886,7 @@ Scanner(ConstUnicode lockDir,    // IN:
       FileSleeper(FILELOCK_PROGRESS_SAMPLE); // relax
    }
 
-   // Clean up anything still on the list; they are no longer important
+   /* Clean up anything still on the list; they are no longer important */
    while (myValues->lockList != NULL) {
       ptr = myValues->lockList;
       myValues->lockList = ptr->next;
@@ -990,10 +990,10 @@ FileUnlockIntrinsic(ConstUnicode pathName,  // IN:
  */
 
 static int
-WaitForPossession(ConstUnicode lockDir,     // IN:
-                  ConstUnicode fileName,    // IN:
-                  LockValues *memberValues, // IN:
-                  LockValues *myValues)     // IN:
+WaitForPossession(ConstUnicode lockDir,      // IN:
+                  ConstUnicode fileName,     // IN:
+                  LockValues *memberValues,  // IN:
+                  LockValues *myValues)      // IN:
 {
    int err = 0;
 
@@ -1116,8 +1116,8 @@ NumberScan(ConstUnicode lockDir,      // IN:
  */
 
 static uint32
-SimpleRandomNumber(const char *machineID,   // IN:
-                   const char *executionID) // IN:
+SimpleRandomNumber(const char *machineID,    // IN:
+                   const char *executionID)  // IN:
 {
    static Atomic_Ptr atomic; /* Implicitly initialized to NULL. --mbellon */
    char *context;
@@ -1675,10 +1675,10 @@ bail:
  */
 
 static int
-ScannerVMX(ConstUnicode lockDir,     // IN:
-           ConstUnicode fileName,    // IN:
-           LockValues *memberValues, // IN:
-           LockValues *myValues)     // IN/OUT:
+ScannerVMX(ConstUnicode lockDir,      // IN:
+           ConstUnicode fileName,     // IN:
+           LockValues *memberValues,  // IN:
+           LockValues *myValues)      // IN/OUT:
 {
    ASSERT(lockDir);
    ASSERT(fileName);
index 772e51c6e6f6dadd233b9e56c1d1967bf55f63a3..2912f888ed0966f1d18e66c8e853e9477116c3dc 100644 (file)
@@ -819,6 +819,37 @@ File_SetTimes(ConstUnicode pathName,      // IN:
 }
 
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * File_SetFilePermissions --
+ *
+ *      Set file permissions.
+ *
+ * Results:
+ *      TRUE if succeed or FALSE if error.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+File_SetFilePermissions(ConstUnicode 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), strerror(errno));
+      return FALSE;
+   }
+   return TRUE;
+}
+
+
 #if !defined(__FreeBSD__) && !defined(sun)
 /*
  *-----------------------------------------------------------------------------
@@ -2787,3 +2818,36 @@ File_IsCharDevice(ConstUnicode pathName)  // IN:
    return (FileAttributes(pathName, &fileData) == 0) &&
            (fileData.fileType == FILE_TYPE_CHARDEVICE);
 }
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * File_SupportsPrealloc --
+ *  
+ *
+ * Results:
+ *      TRUE    if APPLE or file system type is ext2/ext3/ext4
+ *      FALSE   if not supported by default in auto mode
+ *
+ * Side effects:
+ *      None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+File_SupportsPrealloc(const char *file)
+{
+
+#if (defined( __linux__) && !defined(VMX86_SERVER)) 
+   struct statfs statBuf;   
+   if (FileGetStats(file, FALSE, &statBuf) && 
+       statBuf.f_type == EXT4_SUPER_MAGIC) {
+       return TRUE;    
+   }
+#elif APPLE
+   return TRUE
+#endif 
+   return FALSE;
+}
index 73c45e4339d62810c0c3f921b81e1c91ab2683f1..6dc351976e7e1dca5bc711a37a5f4df3969605db 100644 (file)
@@ -257,9 +257,8 @@ static const VixCommandInfo vixCommandInfoTable[] = {
                            VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED),
    VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_OPEN_TEAM,
                            VIX_COMMAND_CATEGORY_PRIVILEGED),
-   VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_FIND_HOST_DEVICES,
-                           VIX_COMMAND_CATEGORY_PRIVILEGED),
-   
+   VIX_DEFINE_UNUSED_COMMAND,
+
    VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_ANSWER_MESSAGE,
                            VIX_COMMAND_CATEGORY_PRIVILEGED),
 
@@ -422,6 +421,15 @@ static const VixCommandInfo vixCommandInfoTable[] = {
    VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_LIST_FILESYSTEMS,
                            VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED),
 
+   VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_CHANGE_DISPLAY_TOPOLOGY,
+                           VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED),
+
+   VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_SUSPEND_AND_RESUME,
+                           VIX_COMMAND_CATEGORY_PRIVILEGED),
+
+   VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_REMOVE_BULK_SNAPSHOT,
+                           VIX_COMMAND_CATEGORY_PRIVILEGED),
+
 };
 
 
@@ -1315,7 +1323,7 @@ abort:
  *
  * VixAsyncOp_ValidateCommandInfoTable --
  *
- *      Checkes that the command info table is generally well-formed.
+ *      Checks that the command info table is generally well-formed.
  *      Makes sure that the table is big enough to contain all the
  *      command op codes and that they are present in the right order.
  *
@@ -1461,3 +1469,165 @@ VixGetCommandInfoForOpCode(int opCode)  // IN
 
    return commandInfo;
 } // VixGetCommandInfoForOpCode
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VixMsg_AllocGenericRequestMsg --
+ *
+ *      Allocate and initialize a generic request message.
+ *
+ *      Assumes the caller holds the lock to 'propertyList'.
+ *
+ * Results:
+ *      Returns VixError.
+ *      Upon retrun, *request will contain either the message with the
+ *      headers properly initialized or NULL.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+VixError
+VixMsg_AllocGenericRequestMsg(int opCode,                         // IN
+                              uint64 cookie,                      // IN
+                              int credentialType,                 // IN
+                              const char *userNamePassword,       // IN
+                              int options,                        // IN
+                              VixPropertyListImpl *propertyList,  // IN
+                              VixCommandGenericRequest **request) // OUT
+{
+   VixError err;
+   VixCommandGenericRequest *requestLocal = NULL;
+   size_t msgHeaderAndBodyLength;
+   char *serializedBufferBody = NULL;
+   size_t serializedBufferLength = 0;
+
+   if (NULL == request) {
+      ASSERT(0);
+      err = VIX_E_FAIL;
+      goto abort;
+   }
+
+   *request = NULL;
+
+   if (NULL != propertyList) {
+      err = VixPropertyList_Serialize(propertyList,
+                                      FALSE,
+                                      &serializedBufferLength,
+                                      &serializedBufferBody);
+      if (VIX_OK != err) {
+         goto abort;
+      }
+   }
+
+   msgHeaderAndBodyLength = sizeof(*requestLocal) + serializedBufferLength;
+   requestLocal = (VixCommandGenericRequest *)
+      VixMsg_AllocRequestMsg(msgHeaderAndBodyLength,
+                             opCode,
+                             cookie,
+                             credentialType,
+                             userNamePassword);
+   if (NULL == requestLocal) {
+      err = VIX_E_FAIL;
+      goto abort;
+   }
+
+   requestLocal->options = options;
+   requestLocal->propertyListSize = serializedBufferLength;
+
+   if (NULL != serializedBufferBody) {
+      char *dst = (char *)request + sizeof(*request);
+      memcpy(dst, serializedBufferBody, serializedBufferLength);
+   }
+
+   *request = requestLocal;
+   err = VIX_OK;
+
+ abort:
+   free(serializedBufferBody);
+
+   return err;
+}  // VixMsg_AllocGenericRequestMsg
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VixMsg_ParseGenericRequestMsg --
+ *
+ *      Extract the options and property list from the request
+ *      message, while validating message.
+ *
+ * Results:
+ *      VixError
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+VixError
+VixMsg_ParseGenericRequestMsg(const VixCommandGenericRequest *request,  // IN
+                              int *options,                             // OUT
+                              VixPropertyListImpl *propertyList)        // OUT
+{
+   VixError err;
+   uint64 headerAndBodyLength;
+
+   if ((NULL == request) || (NULL == options) || (NULL == propertyList)) {
+      ASSERT(0);
+      err = VIX_E_FAIL;
+      goto abort;
+   }
+
+   *options = 0;
+   VixPropertyList_Initialize(propertyList);
+
+   /*
+    * In most cases we will have already called VixMsg_ValidateResponseMsg()
+    * on this request before, but call it here so that this function will
+    * always be sufficient to validate the request.
+    */
+   err = VixMsg_ValidateRequestMsg(request,
+                                   request->header.commonHeader.totalMessageLength);
+   if (VIX_OK != err) {
+      goto abort;
+   }
+
+   if (request->header.commonHeader.totalMessageLength < sizeof *request) {
+      err = VIX_E_INVALID_MESSAGE_BODY;
+      goto abort;
+   }
+
+   headerAndBodyLength = (uint64) request->header.commonHeader.headerLength
+      + request->header.commonHeader.bodyLength;
+
+   if (headerAndBodyLength < ((uint64) sizeof *request
+                              + request->propertyListSize)) {
+      err = VIX_E_INVALID_MESSAGE_BODY;
+      goto abort;
+   }
+
+   if (request->propertyListSize > 0) {
+      const char *serializedBuffer = (const char *) request + sizeof(*request);
+
+      err = VixPropertyList_Deserialize(propertyList,
+                                        serializedBuffer,
+                                        request->propertyListSize);
+      if (VIX_OK != err) {
+         goto abort;
+      }
+   }
+
+   *options = request->options;
+   err = VIX_OK;
+
+ abort:
+
+   return err;
+} // VixMsg_ParseGenericRequestMsg
index 29ed958be3f92e5b1bca2a23100f068e26af9d34..5568ec33bb9b35effa606c4d40a32e56637f254b 100644 (file)
@@ -38,6 +38,7 @@
 #include "strutil.h"
 #include "unityCommon.h"
 #include "util.h"
+#include "xdrutil.h"
 
 
 /*
@@ -103,6 +104,31 @@ static Bool GHITcloTrashFolderGetIcon(RpcInData *data);
 
 static Bool GHIUpdateHost(GHIProtocolHandlerList *handlers);
 
+/*
+ * Wrapper function for the "ghi.guest.trayIcon.sendEvent" RPC.
+ */
+static Bool GHITcloTrayIconSendEvent(RpcInData *data);
+
+/*
+ * Wrapper function for the "ghi.guest.trayIcon.startUpdates" RPC.
+ */
+static Bool GHITcloTrayIconStartUpdates(RpcInData *data);
+
+/*
+ * Wrapper function for the "ghi.guest.trayIcon.stopUpdates" RPC.
+ */
+static Bool GHITcloTrayIconStopUpdates(RpcInData *data);
+
+/*
+ * Wrapper function for the "ghi.guest.setFocusedWindow" RPC.
+ */
+static Bool GHITcloSetFocusedWindow(RpcInData *data);
+
+/*
+ * Wrapper function for the "ghi.guest.getExecInfoHash" RPC.
+ */
+static Bool GHITcloGetExecInfoHash(RpcInData *data);
+
 DynBuf gTcloUpdate;
 static GHIPlatform *ghiPlatformData;
 
@@ -289,6 +315,16 @@ GHI_InitBackdoor(struct RpcIn *rpcIn)   // IN
                                GHITcloTrashFolderAction, NULL);
       RpcIn_RegisterCallbackEx(rpcIn, GHI_RPC_TRASH_FOLDER_GET_ICON,
                                GHITcloTrashFolderGetIcon, NULL);
+      RpcIn_RegisterCallbackEx(rpcIn, GHI_RPC_TRAY_ICON_SEND_EVENT,
+                               GHITcloTrayIconSendEvent, NULL);
+      RpcIn_RegisterCallbackEx(rpcIn, GHI_RPC_TRAY_ICON_START_UPDATES,
+                               GHITcloTrayIconStartUpdates, NULL);
+      RpcIn_RegisterCallbackEx(rpcIn, GHI_RPC_TRAY_ICON_STOP_UPDATES,
+                               GHITcloTrayIconStopUpdates, NULL);
+      RpcIn_RegisterCallbackEx(rpcIn, GHI_RPC_SET_FOCUSED_WINDOW,
+                               GHITcloSetFocusedWindow, NULL);
+      RpcIn_RegisterCallbackEx(rpcIn, GHI_RPC_GET_EXEC_INFO_HASH,
+                               GHITcloGetExecInfoHash, NULL);
    }
 }
 
@@ -1352,5 +1388,360 @@ exit:
     * buffer will be freed by the RPC layer.
     */
    DynXdr_Destroy(&xdrs, !ret);
+   Debug("%s: Exit.\n", __FUNCTION__);
+   return ret;
+}
+
+/**
+ * @brief Send a mouse or keyboard event to a tray icon.
+ *
+ * @param[in] data Pointer to the RpcInData structure for the RPC.
+ *
+ * @retval TRUE  The RPC succeeded.
+ * @retval FALSE The RPC failed.
+ */
+
+Bool
+GHITcloTrayIconSendEvent(RpcInData *data)
+{
+   Bool ret = FALSE;
+   XDR xdrs;
+
+   Debug("%s: Enter.\n", __FUNCTION__);
+
+   /* Check our arguments. */
+   ASSERT(data);
+   ASSERT(data->name);
+   ASSERT(data->argsSize > 0);
+
+   if (!(data && data->name && data->argsSize > 0)) {
+      Debug("%s: Invalid arguments.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
+         __FUNCTION__, data->name, data->argsSize);
+
+   /*
+    * Build an XDR stream from the argument data.
+    *
+    * Note that the argument data begins with args + 1 since there is a space
+    * between the RPC name and the XDR serialization.
+    */
+   xdrmem_create(&xdrs, (char*) data->args + 1, data->argsSize - 1, XDR_DECODE);
+
+   /* Call the platform implementation of our RPC. */
+   ret = GHIPlatformTrayIconSendEvent(ghiPlatformData, &xdrs);
+
+   /* Destroy the XDR stream. */
+   xdr_destroy(&xdrs);
+
+   if (ret == FALSE) {
+      Debug("%s: RPC failed.\n", __FUNCTION__);
+      RPCIN_SETRETVALS(data, "RPC failed", FALSE);
+      goto exit;
+   }
+
+   /*
+    * We don't have any out parameters, so we write empty values into the
+    * result fields of the RpcInData structure.
+    */
+   RPCIN_SETRETVALS(data, "", FALSE);
+
+   /* Set our return value and return to the caller. */
+   ret = TRUE;
+
+exit:
+   Debug("%s: Exit.\n", __FUNCTION__);
+   return ret;
+}
+
+/**
+ * @brief Start sending tray icon updates to the VMX.
+ *
+ * @param[in] data Pointer to the RpcInData structure for the RPC.
+ *
+ * @retval TRUE  The RPC succeeded.
+ * @retval FALSE The RPC failed.
+ */
+
+Bool
+GHITcloTrayIconStartUpdates(RpcInData *data)
+{
+   Bool ret = FALSE;
+
+   Debug("%s: Enter.\n", __FUNCTION__);
+
+   /* Check our arguments. */
+   ASSERT(data);
+   ASSERT(data->name);
+
+   if (!(data && data->name)) {
+      Debug("%s: Invalid arguments.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
+         __FUNCTION__, data->name, data->argsSize);
+
+   if (!GHIPlatformTrayIconStartUpdates(ghiPlatformData)) {
+      Debug("%s: Failed to start tray icon updates.\n", __FUNCTION__);
+      RPCIN_SETRETVALS(data, "Failed to start tray icon updates", FALSE);
+      goto exit;
+   }
+
+   /*
+    * Write the result into the RPC out parameters.
+    */
+   ret = RPCIN_SETRETVALS(data, "", TRUE);
+
+exit:
+   Debug("%s: Exit.\n", __FUNCTION__);
+   return ret;
+}
+
+/**
+ * @brief Stop sending tray icon updates to the VMX.
+ *
+ * @param[in] data Pointer to the RpcInData structure for the RPC.
+ *
+ * @retval TRUE  The RPC succeeded.
+ * @retval FALSE The RPC failed.
+ */
+
+Bool
+GHITcloTrayIconStopUpdates(RpcInData *data)
+{
+   Bool ret = FALSE;
+
+   Debug("%s: Enter.\n", __FUNCTION__);
+
+   /* Check our arguments. */
+   ASSERT(data);
+   ASSERT(data->name);
+
+   if (!(data && data->name)) {
+      Debug("%s: Invalid arguments.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
+         __FUNCTION__, data->name, data->argsSize);
+
+   if (!GHIPlatformTrayIconStopUpdates(ghiPlatformData)) {
+      Debug("%s: Failed to start tray icon updates.\n", __FUNCTION__);
+      RPCIN_SETRETVALS(data, "Failed to start tray icon updates", FALSE);
+      goto exit;
+   }
+
+   /*
+    * Write the result into the RPC out parameters.
+    */
+   ret = RPCIN_SETRETVALS(data, "", TRUE);
+
+exit:
+   return ret;
+}
+
+
+/**
+ * @brief Send the ghi.guest.trayIcon.update RPC to the host.
+ *
+ * @param[in] data Pointer to the RpcInData structure for the RPC.
+ *
+ * @retval TRUE  The RPC succeeded.
+ * @retval FALSE The RPC failed.
+ */
+
+Bool
+GHISendTrayIconUpdateRpc(XDR *xdrs)
+{
+   Bool ret = FALSE;
+   DynBuf outBuf;
+
+   Debug("%s: Enter.\n", __FUNCTION__);
+
+   /* Check our arguments. */
+   ASSERT(xdrs);
+   if (NULL == xdrs) {
+      Debug("%s: Invalid parameter.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   /* Append our RPC name and a space to the DynBuf. */
+   DynBuf_Init(&outBuf);
+   if (!DynBuf_Append(&outBuf,
+                      GHI_RPC_TRAY_ICON_UPDATE,
+                      strlen(GHI_RPC_TRAY_ICON_UPDATE))) {
+      Debug("%s: Failed to append RPC name to DynBuf.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   if (!DynBuf_Append(&outBuf, " ", 1)) {
+      Debug("%s: Failed to append space to DynBuf.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   /* Append the XDR serialized data to the DynBuf. */
+   if (!DynBuf_Append(&outBuf, DynXdr_Get(xdrs), xdr_getpos(xdrs)) )
+   {
+      Debug("%s: Failed to append XDR serialized data to DynBuf.\n",
+            __FUNCTION__);
+      goto exit;
+   }
+
+   if (!RpcOut_SendOneRaw(DynBuf_Get(&outBuf),
+                          DynBuf_GetSize(&outBuf),
+                          NULL,
+                          NULL)) {
+      Debug("%s: Failed to send RPC to host!\n", __FUNCTION__);
+      goto exit;
+   }
+
+   ret = TRUE;
+
+exit:
+   DynBuf_Destroy(&outBuf);
+   Debug("%s: Exit.\n", __FUNCTION__);
+   return ret;
+}
+
+/**
+ * @brief Set the specified window to be focused (NULL or zero window ID indicates
+ * that no window should be focused).
+ *
+ * @param[in] data Pointer to the RpcInData structure for the RPC.
+ *
+ * @retval TRUE  The RPC succeeded.
+ * @retval FALSE The RPC failed.
+ */
+
+Bool
+GHITcloSetFocusedWindow(RpcInData *data)
+{
+   Bool ret = FALSE;
+   XDR xdrs;
+
+   Debug("%s: Enter.\n", __FUNCTION__);
+
+   /* Check our arguments. */
+   ASSERT(data);
+   ASSERT(data->name);
+
+   if (!(data && data->name)) {
+      Debug("%s: Invalid arguments.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
+         __FUNCTION__, data->name, data->argsSize);
+
+   /*
+    * Build an XDR stream from the argument data.
+    *
+    * Note that the argument data begins with args + 1 since there is a space
+    * between the RPC name and the XDR serialization.
+    */
+   xdrmem_create(&xdrs, (char*) data->args + 1, data->argsSize - 1, XDR_DECODE);
+
+   /* Call the platform implementation of our RPC. */
+   ret = GHIPlatformSetFocusedWindow(ghiPlatformData, &xdrs);
+
+   /* Destroy the XDR stream. */
+   xdr_destroy(&xdrs);
+
+   /*
+    * Write the result into the RPC out parameters.
+    */
+   ret = RPCIN_SETRETVALS(data, "", TRUE);
+
+exit:
+   return ret;
+}
+
+
+/**
+ * @brief Get the hash (or timestamp) of information returned by
+ * GHITcloGetBinaryInfo.
+ *
+ * @param[in] data Pointer to the RpcInData structure for the RPC.
+ *
+ * @retval TRUE  The RPC succeeded.
+ * @retval FALSE The RPC failed.
+ */
+
+Bool
+GHITcloGetExecInfoHash(RpcInData *data)
+{
+   Bool ret = TRUE;
+   GHIGetExecInfoHashRequest requestMsg;
+   GHIGetExecInfoHashReply replyMsg;
+   XDR xdrs;
+
+   memset(&requestMsg, 0, sizeof requestMsg);
+   memset(&replyMsg, 0, sizeof replyMsg);
+
+   /* Check our arguments. */
+   ASSERT(data);
+   ASSERT(data->name);
+   ASSERT(data->args);
+
+   if (!(data && data->name && data->args)) {
+      Debug("%s: Invalid arguments.\n", __FUNCTION__);
+      ret = RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
+      goto exit;
+   }
+
+   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
+         __FUNCTION__, data->name, data->argsSize);
+
+   /*
+    * Deserialize the XDR data. Note that the data begins with args + 1 since
+    * there is a space between the RPC name and the XDR serialization.
+    */
+   if (!XdrUtil_Deserialize((char *)data->args + 1, data->argsSize - 1,
+                            xdr_GHIGetExecInfoHashRequest, &requestMsg)) {
+      Debug("%s: Failed to deserialize data\n", __FUNCTION__);
+      ret = RPCIN_SETRETVALS(data, "Failed to deserialize data.", FALSE);
+      goto exit;
+   }
+
+   /*
+    * Call the platform implementation of the RPC handler.
+    */
+   if (!GHIPlatformGetExecInfoHash(ghiPlatformData, &requestMsg, &replyMsg)) {
+      ret = RPCIN_SETRETVALS(data, "Could not get executable info hash.", FALSE);
+      goto exit;
+   }
+
+   /*
+    * Serialize the result data and return.
+    */
+   if (NULL == DynXdr_Create(&xdrs)) {
+      Debug("%s: Failed to create DynXdr structure.\n", __FUNCTION__);
+      ret =  RPCIN_SETRETVALS(data, "Failed to create XDR structure", FALSE);
+      goto exit;
+   }
+
+   if (!xdr_GHIGetExecInfoHashReply(&xdrs, &replyMsg)) {
+      ret = RPCIN_SETRETVALS(data, "Failed to serialize data", FALSE);
+      DynXdr_Destroy(&xdrs, TRUE);
+      goto exit;
+   }
+
+   data->result = DynXdr_Get(&xdrs);
+   data->resultLen = xdr_getpos(&xdrs);
+   data->freeResult = TRUE;
+
+   /*
+    * Destroy the serialized XDR structure but leave the data buffer alone
+    * since it will be freed by the RpcIn layer.
+    */
+   DynXdr_Destroy(&xdrs, FALSE);
+
+exit:
+   VMX_XDR_FREE(xdr_GHIGetExecInfoHashRequest, &requestMsg);
+   VMX_XDR_FREE(xdr_GHIGetExecInfoHashReply, &replyMsg);
+
    return ret;
 }
index ac4a92686287cdbb97c8cea2926db58397a82117..141827256fe472a71a6fbb4189509aedb4baa8cb 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "dynbuf.h"
 #include "unityCommon.h"
+#include "guestrpc/ghiGetExecInfoHash.h"
 #include "guestrpc/ghiProtocolHandler.h"
 
 typedef struct _GHIPlatform GHIPlatform;
@@ -84,13 +85,46 @@ Bool GHIPlatformTrashFolderAction(GHIPlatform* ghip, const XDR *xdrs);
 /* Get the icon for the Trash (aka Recycle Bin) folder. */
 Bool GHIPlatformTrashFolderGetIcon(GHIPlatform *ghip, XDR *xdrs);
 
+/*
+ * Send a mouse event to a tray icon.
+ */
+Bool GHIPlatformTrayIconSendEvent(GHIPlatform *ghip, const XDR *xdrs);
+
+/*
+ * Start sending tray icon updates to the VMX.
+ */
+Bool GHIPlatformTrayIconStartUpdates(GHIPlatform *ghip);
+
+/*
+ * Stop sending tray icon updates to the VMX.
+ */
+Bool GHIPlatformTrayIconStopUpdates(GHIPlatform *ghip);
+
 /* Implemented by ghIntegration.c for use by the platform-specific code */
 Bool GHILaunchMenuChangeRPC(void);
 
 /*
- * Used by the platform-specific code to send the "tools.ghi.trash.change" RPC
- * to the host.
+ * Used by the platform-specific code to send the "ghi.guest.trashFolder.state"
+ * RPC to the host.
  */
 Bool GHISendTrashFolderStateRPC(XDR *xdrs);
 
+/*
+ * Used by the platform-specific code to send the "ghi.guest.trayIcon.update"
+ * RPC to the host.
+ */
+Bool GHISendTrayIconUpdateRpc(XDR *xdrs);
+
+/*
+ * Set the specified window to be focused.
+ */
+Bool GHIPlatformSetFocusedWindow(GHIPlatform *ghip, const XDR *xdrs);
+
+/*
+ * Get the hash (or timestamp) of information returned by get.binary.info.
+ */
+Bool GHIPlatformGetExecInfoHash(GHIPlatform *ghip,
+                                const GHIGetExecInfoHashRequest *request,
+                                GHIGetExecInfoHashReply *reply);
+
 #endif
index 75b14abd43f35fdedb950e6585ecadefce4d2b5b..312d42d372ac9912f77aabe17752cb40a10cc02b 100644 (file)
@@ -907,7 +907,15 @@ GHIPlatformGetDesktopName(void)
    Window temp2;        // throwaway
    Window *children = NULL;
    unsigned int nchildren;
-   const char *retval = NULL;
+   static const char *desktopEnvironment = NULL;
+
+   /*
+    * NB: While window managers may change during vmware-user's execution, TTBOMK
+    * desktop environments cannot, so this is safe.
+    */
+   if (desktopEnvironment) {
+      return desktopEnvironment;
+   }
 
    display = gdk_x11_get_default_xdisplay();
    rootWindow = DefaultRootWindow(display);
@@ -916,26 +924,45 @@ GHIPlatformGetDesktopName(void)
       return NULL;
    }
 
-   for (i = 0; i < nchildren && !retval; i++) {
-      char *name = NULL;
+   for (i = 0; i < nchildren && !desktopEnvironment; i++) {
+      XClassHint wmClass = { 0, 0 };
       int j;
 
-      if ((XFetchName(display, children[i], &name) == 0) ||
-          name == NULL) {
-         continue;
-      }
+      /*
+       * Try WM_CLASS first, then try WM_NAME.
+       */
 
-      for (j = 0; j < ARRAYSIZE(clientMappings) && !retval; j++) {
-         if (!strcmp(clientMappings[j][0], name)) {
-            retval = clientMappings[j][1];
+      if (XGetClassHint(display, children[i], &wmClass) != 0) {
+         for (j = 0; j < ARRAYSIZE(clientMappings) && !desktopEnvironment; j++) {
+            if ((strcasecmp(clientMappings[j][0], wmClass.res_name) == 0) ||
+                (strcasecmp(clientMappings[j][0], wmClass.res_class) == 0)) {
+               desktopEnvironment = clientMappings[j][1];
+            }
          }
+         XFree(wmClass.res_name);
+         XFree(wmClass.res_class);
       }
 
-      XFree(name);
+      if (!desktopEnvironment) {
+         char *name = NULL;
+
+         if ((XFetchName(display, children[i], &name) == 0) ||
+             name == NULL) {
+            continue;
+         }
+
+         for (j = 0; j < ARRAYSIZE(clientMappings) && !desktopEnvironment; j++) {
+            if (!strcmp(clientMappings[j][0], name)) {
+               desktopEnvironment = clientMappings[j][1];
+            }
+         }
+
+         XFree(name);
+      }
    }
 
    XFree(children);
-   return retval;
+   return desktopEnvironment;
 }
 
 
@@ -969,9 +996,9 @@ GHIPlatformIsMenuItemAllowed(GHIPlatform *ghip, // IN:
     * Examine the "NoDisplay" and "Hidden" properties.
     */
    if (g_key_file_get_boolean(keyfile,
-                             G_KEY_FILE_DESKTOP_GROUP,
-                             G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY,
-                             NULL) ||
+                              G_KEY_FILE_DESKTOP_GROUP,
+                              G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY,
+                              NULL) ||
        g_key_file_get_boolean(keyfile,
                               G_KEY_FILE_DESKTOP_GROUP,
                               G_KEY_FILE_DESKTOP_KEY_HIDDEN,
@@ -1388,7 +1415,7 @@ GHIPlatformReadApplicationsDir(GHIPlatform *ghip, // IN
       if (!strcmp(dent->d_name, ".") ||
           !strcmp(dent->d_name, "..") ||
           !strcmp(dent->d_name, ".hidden")) {
-       continue;
+         continue;
       }
 
       subpathLen = Str_Sprintf(subpath, sizeof subpath, "%s/%s", dir, dent->d_name);
@@ -1409,8 +1436,8 @@ GHIPlatformReadApplicationsDir(GHIPlatform *ghip, // IN
       } else if ((dent->d_type == DT_REG ||
                   (dent->d_type == DT_UNKNOWN
                    && S_ISREG(sbuf.st_mode)))
-                && StrUtil_EndsWith(dent->d_name, ".desktop")) {
-        GHIPlatformReadDesktopFile(ghip, subpath);
+                 && StrUtil_EndsWith(dent->d_name, ".desktop")) {
+         GHIPlatformReadDesktopFile(ghip, subpath);
       }
    }
 
@@ -1450,7 +1477,7 @@ GHIPlatformReadAllApplications(GHIPlatform *ghip) // IN
 
       for (i = 0; i < ARRAYSIZE(desktopDirs); i++) {
          if (StrUtil_StartsWith(desktopDirs[i], "~/")) {
-           char cbuf[PATH_MAX];
+            char cbuf[PATH_MAX];
 
             Str_Sprintf(cbuf, sizeof cbuf, "%s/%s",
                         g_get_home_dir(), desktopDirs[i] + 2);
@@ -2450,8 +2477,8 @@ GHIPlatformShellAction(GHIPlatform *ghip,       // IN: platform-specific state
 
 Bool
 GHIPlatformShellUrlOpen(GHIPlatform *ghip,      // IN: platform-specific state
-                       const char *fileUtf8,   // IN: command/file
-                       const char *actionUtf8) // IN: action
+                        const char *fileUtf8,   // IN: command/file
+                        const char *actionUtf8) // IN: action
 {
 #ifdef GTK2
    char **fileArgv = NULL;
@@ -2735,3 +2762,92 @@ GHIPlatformTrashFolderGetIcon(GHIPlatform *ghip,
    ASSERT(xdrs);
    return FALSE;
 }
+
+/* @brief Send a mouse or keyboard event to a tray icon.
+ *
+ * @param[in] ghip Pointer to platform-specific GHI data.
+ *
+ * @retval TRUE Operation Succeeded.
+ * @retval FALSE Operation Failed.
+ */
+
+Bool
+GHIPlatformTrayIconSendEvent(GHIPlatform *ghip,
+                             const XDR   *xdrs)
+{
+   ASSERT(ghip);
+   ASSERT(xdrs);
+   return FALSE;
+}
+
+/* @brief Start sending tray icon updates to the VMX.
+ *
+ * @param[in] ghip Pointer to platform-specific GHI data.
+ *
+ * @retval TRUE Operation Succeeded.
+ * @retval FALSE Operation Failed.
+ */
+
+Bool
+GHIPlatformTrayIconStartUpdates(GHIPlatform *ghip)
+{
+   ASSERT(ghip);
+   return FALSE;
+}
+
+/* @brief Stop sending tray icon updates to the VMX.
+ *
+ * @param[in] ghip Pointer to platform-specific GHI data.
+ *
+ * @retval TRUE Operation Succeeded.
+ * @retval FALSE Operation Failed.
+ */
+
+Bool
+GHIPlatformTrayIconStopUpdates(GHIPlatform *ghip)
+{
+   ASSERT(ghip);
+   return FALSE;
+}
+
+/* @brief Set a window to be focused.
+ *
+ * @param[in] ghip Pointer to platform-specific GHI data.
+ * @param[in] xdrs Pointer to serialized data from the host.
+ *
+ * @retval TRUE Operation Succeeded.
+ * @retval FALSE Operation Failed.
+ */
+
+Bool
+GHIPlatformSetFocusedWindow(GHIPlatform *ghip,
+                            const XDR   *xdrs)
+{
+   ASSERT(ghip);
+   ASSERT(xdrs);
+   return FALSE;
+}
+
+
+/**
+ * @brief Get the hash (or timestamp) of information returned by
+ * GHIPlatformGetBinaryInfo.
+ *
+ * @param[in]  ghip     Pointer to platform-specific GHI data.
+ * @param[in]  request  Request containing which executable to get the hash for.
+ * @param[out] reply    Reply to be filled with the hash.
+ *
+ * @retval TRUE Operation succeeded.
+ * @retval FALSE Operation failed.
+ */
+
+Bool GHIPlatformGetExecInfoHash(GHIPlatform *ghip,
+                                const GHIGetExecInfoHashRequest *request,
+                                GHIGetExecInfoHashReply *reply)
+{
+   ASSERT(ghip);
+   ASSERT(request);
+   ASSERT(reply);
+
+   return FALSE;
+}
index c2b41c8e2ba7db4c2d995dd44758f2428572a52e..6a35d1ab54679e232557b1d15390d479dc5acd40 100644 (file)
@@ -35,6 +35,7 @@ extern "C" {
 #include <stdlib.h>     // for free, system
 #include <string.h>
 #include <strings.h>
+#include <unistd.h>
 
 #include <glib.h>
 
@@ -83,7 +84,8 @@ GuestAppX11OpenUrl(const char *url, // IN
    gboolean spawnSuccess;
    GError *gerror = NULL;
 
-   char **argv = NULL;
+   char *argv[4];
+   char **parsedArgv = NULL;
    char *newNetscapeBuf = NULL;
    Bool success = FALSE;
 
@@ -107,42 +109,35 @@ GuestAppX11OpenUrl(const char *url, // IN
       if (!newNetscapeBuf) {
          goto abort;
       }
-      argv = g_malloc(4 * sizeof *argv);
       argv[0] = (char *)gBrowser;
       argv[1] = "-remote";
       argv[2] = newNetscapeBuf;
       argv[3] = NULL;
    } else {
       gint argc;
+      gboolean parsed;
       /*
-       * See GuestAppDetectBrowser(): our browser command could come from gconf,
-       * in which case it's a command line that we have to parse, so that we
-       * can put the URL in the right place before executing the child process.
+       * See GuestAppDetectBrowser(): we already made sure we can parse the
+       * command and that it has a placeholder, so just assert that is still
+       * the case here.
        */
-      if (!g_shell_parse_argv(gBrowser, &argc, &argv, &gerror)) {
-         Debug("Error parsing browser command line: %s\n", gerror->message);
-         g_clear_error(&gerror);
-         goto abort;
-      }
+      parsed = g_shell_parse_argv(gBrowser, &argc, &parsedArgv, NULL);
+      ASSERT(parsed);
+
       if (argc > 1) {
-         /*
-          * If the browser is a command line, we expect "%s" to be the URL
-          * placeholder. If not found, bail out.
-          */
          gint i;
+
          for (i = 0; i < argc; i++) {
-            if (strcmp(argv[i], "%s") == 0) {
-               argv[i] = (char *) url;
+            if (strcmp(parsedArgv[i], "%s") == 0) {
+               g_free(parsedArgv[i]);
+               parsedArgv[i] = g_strdup(url);
                break;
             }
          }
-         if (i == argc) {
-            Debug("Browser command (%s) doesn't have an URL placeholder.\n", gBrowser);
-            goto abort;
-         }
+         ASSERT(i < argc);
       } else {
-         g_free(argv);
-         argv = g_malloc(3 * sizeof *argv);
+         g_strfreev(parsedArgv);
+         parsedArgv = NULL;
          argv[0] = (char *)gBrowser;
          argv[1] = (char *)url;
          argv[2] = NULL;
@@ -154,7 +149,7 @@ GuestAppX11OpenUrl(const char *url, // IN
     * help is showing.
     */
    spawnSuccess = g_spawn_async(NULL,     // inherit working directory
-                                argv,
+                                (parsedArgv != NULL) ? parsedArgv : argv,
                                 /*
                                 * XXX  Please don't hate me for casting off the
                                 * qualifier here.  Glib does -not- modify the
@@ -181,7 +176,7 @@ GuestAppX11OpenUrl(const char *url, // IN
    success = TRUE;
 
 abort:
-   g_free(argv);
+   g_strfreev(parsedArgv);
    free(newNetscapeBuf);
    return success;
 }
@@ -255,7 +250,8 @@ GuestAppDetectBrowser(void)
       char *argv[] = {
          "gconftool-2",
          "--get",
-         "/desktop/gnome/url-handlers/http/command"
+         "/desktop/gnome/url-handlers/http/command",
+         NULL
       };
       gboolean success;
       gchar *out = NULL;
@@ -264,34 +260,85 @@ GuestAppDetectBrowser(void)
 
       success =  g_spawn_sync(NULL,
                               argv,
-                               (char **)guestAppSpawnEnviron,
-                               G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
-                               NULL,
-                               NULL,
-                               &out,
-                               NULL,
-                               &status,
-                               &err);
+                              (char **)guestAppSpawnEnviron,
+                              G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
+                              NULL,
+                              NULL,
+                              &out,
+                              NULL,
+                              &status,
+                              &err);
+
+      /*
+       * gconftool-2 exits with a success status when the key we're querying is
+       * empty (or doesn't exist?), so make sure the output string is also empty
+       * (with no new lines or anything).
+       */
+      if (out != NULL) {
+         g_strchomp(out);
+      }
+
       if (!success || !WIFEXITED(status) || WEXITSTATUS(status) != 0 ||
           out == NULL || strlen(out) == 0) {
           Warning("Failed to invoke gconftool-2: exit code %d (%s)\n",
                   WEXITSTATUS(status),
                   (err != NULL) ? err->message : "");
           g_clear_error(&err);
+          g_free(out);
       } else {
-         buf = g_strchomp(out);
-         gBrowserIsMalloced = TRUE;
-         goto exit;
+         /*
+          * We got data from gconftool-2, but it may still be invalid (e.g., the
+          * user has configured a browser that doesn't exist). Try to detect
+          * that case and fallback to our regular "brute force" detection if
+          * we can't use the command.
+          */
+         int argc = 0;
+         char **command = NULL;
+         if (g_shell_parse_argv(out, &argc, &command, NULL) && argc > 0) {
+            if ((g_path_is_absolute(command[0]) && !access(command[0], X_OK)) ||
+                !GuestApp_FindProgram(command[0])) {
+               Debug("Cannot find or execute user-defined default browser '%s'.\n",
+                     command[0]);
+            } else {
+               /* We expect "%s" to be the URL placeholder. If not found, fall back. */
+               gint i;
+               for (i = 0; i < argc; i++) {
+                  if (strcmp(command[i], "%s") == 0) {
+                     break;
+                  }
+               }
+               if (i < argc) {
+                  buf = out;
+                  gBrowserIsMalloced = TRUE;
+                  g_strfreev(command);
+                  goto exit;
+               } else {
+                  Debug("Browser command (%s) doesn't have an URL placeholder.\n", out);
+               }
+            }
+         } else {
+            Debug("Failed to parse custom user-defined browser command (%s).\n", out);
+         }
+
+         g_free(out);
+         g_strfreev(command);
       }
    }
 
    if (((getenv("KDE_FULL_SESSION") != NULL &&
                 !strcmp(getenv("KDE_FULL_SESSION"), "true")) ||
                GuestAppFindX11Client("ksmserver") ||
-               GuestAppFindX11Client("startkde")) &&
-              GuestApp_FindProgram("konqueror")) {
-      buf = "konqueror";
-   } else if (GuestApp_FindProgram("mozilla-firefox")) {
+               GuestAppFindX11Client("startkde"))) {
+      if (GuestApp_FindProgram("kde-open")) {
+         buf = "kde-open";
+         goto exit;
+      } else if (GuestApp_FindProgram("konqueror")) {
+         buf = "konqueror";
+         goto exit;
+      }
+   }
+
+   if (GuestApp_FindProgram("mozilla-firefox")) {
       buf = "mozilla-firefox";
    } else if (GuestApp_FindProgram("firefox")) {
       buf = "firefox";
index 65c4777e28bf2a54f3054dc286b854b56c6c84d0..7d1c16277a0b57593a9cf88a0e934f7aef9cc00b 100644 (file)
@@ -296,8 +296,7 @@ GuestInfoGetDiskInfo(PGuestDiskInfo di)
 
    for (i = 0; i < pl->size; i++) {
       nextPartition = pl->partitions[i];
-      if (!strlen(nextPartition.comment) ||
-          strcmp(nextPartition.comment, WIPER_DEVICE_MAPPER_STRING) == 0) {
+      if (!strlen(nextPartition.comment)) {
          PPartitionEntry newPartitionList;
          unsigned char *error;
          error = WiperSinglePartition_GetSpace(&nextPartition, &freeBytes, &totalBytes);
index 68f47ec4451d08d8598efb0b3d4cfb697e9c11a8..c59702606575936e49648459820d6f5dc66042ba 100644 (file)
@@ -20,6 +20,7 @@ noinst_LTLIBRARIES = libGuestRpc.la
 libGuestRpc_la_SOURCES =
 libGuestRpc_la_SOURCES += cpFileContents_xdr.c
 libGuestRpc_la_SOURCES += ghiGetBinaryHandlers_xdr.c
+libGuestRpc_la_SOURCES += ghiGetExecInfoHash_xdr.c
 libGuestRpc_la_SOURCES += ghiProtocolHandler_xdr.c
 libGuestRpc_la_SOURCES += guestlibV3_xdr.c
 libGuestRpc_la_SOURCES += nicinfo_xdr.c
@@ -35,6 +36,8 @@ CLEANFILES += cpFileContents.h
 CLEANFILES += cpFileContents_xdr.c
 CLEANFILES += ghiGetBinaryHandlers.h
 CLEANFILES += ghiGetBinaryHandlers_xdr.c
+CLEANFILES += ghiGetExecInfoHash.h
+CLEANFILES += ghiGetExecInfoHash_xdr.c
 CLEANFILES += ghiProtocolHandler.h
 CLEANFILES += ghiProtocolHandler_xdr.c
 CLEANFILES += guestlibV3.h
@@ -47,6 +50,7 @@ CLEANFILES += unityActive_xdr.c
 EXTRA_DIST =
 EXTRA_DIST += cpFileContents.x
 EXTRA_DIST += ghiGetBinaryHandlers.x
+EXTRA_DIST += ghiGetExecInfoHash.x
 EXTRA_DIST += ghiProtocolHandler.x
 EXTRA_DIST += guestlibV3.x
 EXTRA_DIST += nicinfo.x
@@ -89,6 +93,19 @@ ghiGetBinaryHandlers.h: ghiGetBinaryHandlers.x
 ghiGetBinaryHandlers_xdr.c: ghiGetBinaryHandlers.x ghiGetBinaryHandlers.h
        $(RPCGEN) $(RPCGENFLAGS) -c -o $@ $(builddir)/ghiGetBinaryHandlers.x
 
+ghiGetExecInfoHash.h: ghiGetExecInfoHash.x
+       if [ $(top_builddir) != $(top_srcdir) ]; then                           \
+          cp -f $(top_srcdir)/lib/guestRpc/ghiGetExecInfoHash.x $(builddir); \
+       fi
+       $(RPCGEN) $(RPCGENFLAGS) -h -o $@ $(builddir)/ghiGetExecInfoHash.x
+       $(SED) 's,rpc/rpc\.h,vmxrpc.h,' $@ > $@.tmp
+       mv $@.tmp $@
+       $(MKDIR_P) $(top_builddir)/lib/include/guestrpc
+       cp $@ $(top_builddir)/lib/include/guestrpc
+
+ghiGetExecInfoHash_xdr.c: ghiGetExecInfoHash.x ghiGetExecInfoHash.h
+       $(RPCGEN) $(RPCGENFLAGS) -c -o $@ $(builddir)/ghiGetExecInfoHash.x
+
 ghiProtocolHandler.h: ghiProtocolHandler.x
        if [ $(top_builddir) != $(top_srcdir) ]; then                           \
           cp -f $(top_srcdir)/lib/guestRpc/ghiProtocolHandler.x $(builddir);   \
diff --git a/open-vm-tools/lib/guestRpc/ghiGetExecInfoHash.x b/open-vm-tools/lib/guestRpc/ghiGetExecInfoHash.x
new file mode 100644 (file)
index 0000000..989ed01
--- /dev/null
@@ -0,0 +1,71 @@
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+/*
+* ghiGetExecInfoHash.x --
+*
+*    Definition of the data structures used in the GuestRpc commands to
+*    get the hash of information returned by the get.binary.info RPC.
+*/
+
+#include "ghiCommonDefines.h"
+
+#define GHI_EXEC_INFO_HASH_MAX_LEN 1024
+
+/*
+* Enumerates the different versions of the messages.
+*/
+enum GHIGetExecInfoHashVersion {
+  GHI_GET_EXEC_INFO_HASH_V1 = 1
+};
+
+/*
+* The structures used for version 1 of the messages.
+*/
+struct GHIGetExecInfoHashRequestV1 {
+  /*
+    * A string identifier for the executable path.
+    */
+   string execPath<GHI_HANDLERS_ACTIONURI_MAX_PATH>;
+};
+struct GHIGetExecInfoHashReplyV1 {
+  /*
+    * A string identifier for the hash.
+    */
+   string execHash<GHI_EXEC_INFO_HASH_MAX_LEN>;
+};
+
+/*
+ * This defines the protocol for 'getExecInfoHash' request and reply messages.
+ *
+ * The union allows us to introduce new versions of the protocol later by
+ * creating new values in the enumeration, without having to change much of
+ * the code calling the (de)serialization functions.
+ *
+ * Since the union doesn't have a default case, de-serialization will fail if
+ * an unknown version is provided on the wire.
+ */
+union GHIGetExecInfoHashRequest switch (GHIGetExecInfoHashVersion ver) {
+case GHI_GET_EXEC_INFO_HASH_V1:
+   struct GHIGetExecInfoHashRequestV1 *requestV1;
+};
+union GHIGetExecInfoHashReply switch (GHIGetExecInfoHashVersion ver) {
+case GHI_GET_EXEC_INFO_HASH_V1:
+   struct GHIGetExecInfoHashReplyV1 *replyV1;
+};
+
index f97c679b6e042e31b1db6a15aa936e939d6be07a..dc92be0dc77c91886e386545b0b9e0d7f870a364 100644 (file)
@@ -96,7 +96,7 @@ CPName_GetComponent(char const *begin,   // IN: Beginning of buffer
          /* Found a NUL */
 
          if (walk == begin) {
-            Log("CPName_GetComponent: error: first char can't be NUL\n");
+            Log("%s: error: first char can't be NUL\n", __FUNCTION__);
             return -1;
          }
 
@@ -156,7 +156,7 @@ CPNameEscapeAndConvertFrom(char const **bufIn, // IN/OUT: Input to convert
       char const *savedOutConst = savedBufOut;
       size_t savedOutSize = *outSize;
       if (inputSize > *outSize) {
-         Log("CPNameEscapeAndConvertFrom: error: not enough room for escaping\n");
+         Log("%s: error: not enough room for escaping\n", __FUNCTION__);
          return -1;
       }
 
@@ -228,14 +228,14 @@ CPNameConvertFrom(char const **bufIn, // IN/OUT: Input to convert
 
       len = CPName_GetComponent(in, inEnd, &next);
       if (len < 0) {
-         Log("CPNameConvertFrom: error: get next component failed\n");
+         Log("%s: error: get next component failed\n", __FUNCTION__);
          return len;
       }
 
       /* Bug 27926 - preventing escaping from shared folder. */
       if ((len == 1 && *in == '.') ||
           (len == 2 && in[0] == '.' && in[1] == '.')) {
-         Log("CPNameConvertFrom: error: found dot/dotdot\n");
+         Log("%s: error: found dot/dotdot\n", __FUNCTION__);
          return -1;
       }
 
@@ -246,7 +246,7 @@ CPNameConvertFrom(char const **bufIn, // IN/OUT: Input to convert
 
       newLen = ((int) myOutSize) - len - 1;
       if (newLen < 0) {
-         Log("CPNameConvertFrom: error: not enough room\n");
+         Log("%s: error: not enough room\n", __FUNCTION__);
          return -1;
       }
       myOutSize = (size_t) newLen;
@@ -262,7 +262,7 @@ CPNameConvertFrom(char const **bufIn, // IN/OUT: Input to convert
 
    /* NUL terminate */
    if (myOutSize < 1) {
-      Log("CPNameConvertFrom: error: not enough room\n");
+      Log("%s: error: not enough room\n", __FUNCTION__);
       return -1;
    }
    *out = '\0';
index a7c2fc08bef34796aded5c57d46801d3692435f3..2da57516ce250a7d1bc40c47b87c217f9f87a154 100644 (file)
@@ -127,7 +127,7 @@ CPName_ConvertFromRoot(char const **bufIn, // IN/OUT: Input to convert
     */
    len = CPName_GetComponent(*bufIn, *bufIn + *inSize, &next);
    if (len < 0) {
-      Log("CPName_ConvertFromRoot: get first component failed\n");
+      Log("%s: get first component failed\n", __FUNCTION__);
       return HGFS_NAME_STATUS_FAILURE;
    }
 
index 4a54b20b8acc150618ee88338a48b7d0a0c45a4f..352e41e6a002f38e51bee5f337fdcdd8235a5265 100644 (file)
@@ -56,6 +56,7 @@
  * NOTE: This flag is only meant to be used while testing. This should
  *       _always_ be undefined when checking code in.
  */
+
 #if 0
 #define HGFS_ASSERT_CLIENT(op) \
    do { \
@@ -75,6 +76,7 @@
  * NOTE: This flag is only meant to be used while testing. This should
  *       _always_ be undefined when checking code in.
  */
+
 #if 0
 #define HGFS_ASSERT_MINIMUM_OP(op) \
    do { \
@@ -834,6 +836,7 @@ HgfsFileHasServerLock(const char *utf8Name,             // IN: Name in UTF8
    SyncMutex_Lock(&session->nodeArrayLock);
    for (i = 0; i < session->numNodes; i++) {
       HgfsFileNode *existingFileNode = &session->nodeArray[i];
+
       if ((existingFileNode->state == FILENODE_STATE_IN_USE_CACHED) &&
           (existingFileNode->serverLock != HGFS_LOCK_NONE) &&
           (!stricmp(existingFileNode->utf8Name, utf8Name))) {
@@ -1171,13 +1174,12 @@ HgfsServerCheckOpenFlagsForShare(HgfsFileOpenInfo *openInfo,// IN: Hgfs file han
    /* The share name is the first component of the cross-platform name. */
    len = CPName_GetComponent(openInfo->cpName, inEnd, &next);
    if (len < 0) {
-      LOG(4, ("HgfsServerCheckOpenFlagsForShare: get first component failed\n"));
+      LOG(4, ("%s: get first component failed\n", __FUNCTION__));
       status = FALSE;
       goto exit;
    }
 
-   nameStatus = HgfsServerPolicy_GetShareMode(openInfo->cpName,
-                                              len,
+   nameStatus = HgfsServerPolicy_GetShareMode(openInfo->cpName, len,
                                               &shareMode);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
       status = FALSE;
@@ -1196,6 +1198,7 @@ HgfsServerCheckOpenFlagsForShare(HgfsFileOpenInfo *openInfo,// IN: Hgfs file han
           * if the file does not exist, which it is okay, as creating
           * a new file is not allowed and should be failed.
           */
+
          *flags = HGFS_OPEN;
       }
    }
@@ -1277,13 +1280,14 @@ HgfsGetNewNode(HgfsSessionInfo *session)  // IN: session info
    ASSERT(session);
    ASSERT(session->nodeArray);
 
-   LOG(4, ("HgfsGetNewNode: entered\n"));
+   LOG(4, ("%s: entered\n", __FUNCTION__));
 
    if (!DblLnkLst_IsLinked(&session->nodeFreeList)) {
       /*
        * This has to be unsigned and with maximum bit length. This is
        * required to take care of "negative" differences as well.
        */
+
       uintptr_t ptrDiff;
 
       if (DOLOG(4)) {
@@ -1296,7 +1300,8 @@ HgfsGetNewNode(HgfsSessionInfo *session)  // IN: session info
       newMem = (HgfsFileNode *)realloc(session->nodeArray,
                                        newNumNodes * sizeof *(session->nodeArray));
       if (!newMem) {
-         LOG(4, ("HgfsGetNewNode: can't realloc more nodes\n"));
+         LOG(4, ("%s: can't realloc more nodes\n", __FUNCTION__));
+
          return NULL;
       }
 
@@ -1311,19 +1316,21 @@ HgfsGetNewNode(HgfsSessionInfo *session)  // IN: session info
           *
           * We'll need to lock this if we multithread.
           */
-         LOG(4, ("Rebasing pointers, diff is %"FMTSZ"u, sizeof node is %"FMTSZ"u\n",
-                  ptrDiff, sizeof(HgfsFileNode)));
+
+         LOG(4, ("Rebasing pointers, diff is %"FMTSZ"u, sizeof node is "
+                  "%"FMTSZ"u\n", ptrDiff, sizeof(HgfsFileNode)));
          LOG(4, ("old: %p new: %p\n", session->nodeArray, newMem));
-         ASSERT(newMem == (HgfsFileNode*)((char*)session->nodeArray + ptrDiff));
+         ASSERT(newMem == (HgfsFileNode *)((char*)session->nodeArray + ptrDiff));
 
 #define HgfsServerRebase(_ptr, _type)                                   \
-   if ((size_t)((char *)_ptr - (char *)session->nodeArray) < oldSize) {          \
+   if ((size_t)((char *)_ptr - (char *)session->nodeArray) < oldSize) { \
       _ptr = (_type *)((char *)_ptr + ptrDiff);                         \
    }
 
          /*
           * Rebase the links of all file nodes
           */
+
          for (i = 0; i < session->numNodes; i++) {
             HgfsServerRebase(newMem[i].links.prev, DblLnkLst_Links)
             HgfsServerRebase(newMem[i].links.next, DblLnkLst_Links)
@@ -1377,7 +1384,8 @@ HgfsGetNewNode(HgfsSessionInfo *session)  // IN: session info
  *
  *    Free its localname, clear its fields, return it to the free list.
  *
- *    The session's nodeArrayLock should be acquired prior to calling this function.
+ *    The session's nodeArrayLock should be acquired prior to calling this
+ *    function.
  *
  * Results:
  *    None
@@ -1395,10 +1403,8 @@ HgfsRemoveFileNode(HgfsFileNode *node,        // IN: file node
 {
    ASSERT(node);
 
-   LOG(4, ("HgfsRemoveFileNode: handle %u, name %s, fileId %"FMT64"u\n",
-           HgfsFileNode2Handle(node),
-           node->utf8Name,
-           node->localId.fileId));
+   LOG(4, ("%s: handle %u, name %s, fileId %"FMT64"u\n", __FUNCTION__,
+           HgfsFileNode2Handle(node), node->utf8Name, node->localId.fileId));
 
    if (node->shareName) {
       free(node->shareName);
@@ -1480,7 +1486,8 @@ HgfsFreeFileNode(HgfsHandle handle,         // IN: Handle to free
  *    Gets a free node off the free list, sets its name, localId info,
  *    file descriptor and permissions.
  *
- *    The session's nodeArrayLock should be acquired prior to calling this function.
+ *    The session's nodeArrayLock should be acquired prior to calling this
+ *    function.
  *
  * Results:
  *    A pointer to the newly added node on success
@@ -1514,13 +1521,15 @@ HgfsAddNewFileNode(HgfsFileOpenInfo *openInfo,  // IN: open info struct
    /* Get an unused node */
    newNode = HgfsGetNewNode(session);
    if (!newNode) {
-      LOG(4, ("HgfsAddNewFileNode: out of memory\n"));
+      LOG(4, ("%s: out of memory\n", __FUNCTION__));
+
       return NULL;
    }
 
    /* Set new node's fields */
    if (!HgfsServerGetOpenMode(openInfo, &newNode->mode)) {
       HgfsRemoveFileNode(newNode, session);
+
       return NULL;
    }
 
@@ -1528,10 +1537,12 @@ HgfsAddNewFileNode(HgfsFileOpenInfo *openInfo,  // IN: open info struct
     * Save a copy of the share name so we can look up its
     * access mode at various times over the node's lifecycle.
     */
+
    newNode->shareName = malloc(shareNameLen + 1);
    if (newNode->shareName == NULL) {
-      LOG(4, ("HgfsAddNewFileNode: out of memory\n"));
+      LOG(4, ("%s: out of memory\n", __FUNCTION__));
       HgfsRemoveFileNode(newNode, session);
+
       return NULL;
    }
    memcpy(newNode->shareName, shareName, shareNameLen);
@@ -1541,8 +1552,9 @@ HgfsAddNewFileNode(HgfsFileOpenInfo *openInfo,  // IN: open info struct
    newNode->utf8NameLen = strlen(openInfo->utf8Name);
    newNode->utf8Name = malloc(newNode->utf8NameLen + 1);
    if (newNode->utf8Name == NULL) {
-      LOG(4, ("HgfsAddNewFileNode: out of memory\n"));
+      LOG(4, ("%s: out of memory\n", __FUNCTION__));
       HgfsRemoveFileNode(newNode, session);
+
       return NULL;
    }
    memcpy(newNode->utf8Name, openInfo->utf8Name, newNode->utf8NameLen);
@@ -1554,6 +1566,7 @@ HgfsAddNewFileNode(HgfsFileOpenInfo *openInfo,  // IN: open info struct
    newNode->shareAccess = (openInfo->mask & HGFS_OPEN_VALID_SHARE_ACCESS) ?
       openInfo->shareAccess : HGFS_DEFAULT_SHARE_ACCESS;
    newNode->flags = 0;
+
    if (append) {
       newNode->flags |= HGFS_FILE_NODE_APPEND_FL;
    }
@@ -1567,8 +1580,9 @@ HgfsAddNewFileNode(HgfsFileOpenInfo *openInfo,  // IN: open info struct
    newNode->serverLock = openInfo->acquiredLock;
    newNode->state = FILENODE_STATE_IN_USE_NOT_CACHED;
 
-   LOG(4, ("HgfsAddNewFileNode: got new node, handle %u\n",
+   LOG(4, ("%s: got new node, handle %u\n", __FUNCTION__,
            HgfsFileNode2Handle(newNode)));
+
    return newNode;
 }
 
@@ -1582,7 +1596,8 @@ HgfsAddNewFileNode(HgfsFileOpenInfo *openInfo,  // IN: open info struct
  *    the maximum number of entries then the first node is removed. The
  *    first node should be the least recently used.
  *
- *    The session's nodeArrayLock should be acquired prior to calling this function.
+ *    The session's nodeArrayLock should be acquired prior to calling this
+ *    function.
  *
  * Results:
  *    TRUE on success
@@ -1604,13 +1619,16 @@ HgfsAddToCacheInternal(HgfsHandle handle,         // IN: HGFS file handle
    if (HgfsIsCachedInternal(handle, session)) {
       ASSERT((node = HgfsHandle2FileNode(handle, session)) &&
              node->state == FILENODE_STATE_IN_USE_CACHED);
+
       return TRUE;
    }
 
    /* Remove the LRU node if the list is full. */
    if (session->numCachedOpenNodes == maxCachedOpenNodes) {
       if (!HgfsRemoveLruNode(session)) {
-         LOG(4, ("HgfsAddToCacheInternal: Unable to remove LRU node from cache.\n"));
+         LOG(4, ("%s: Unable to remove LRU node from cache.\n",
+                 __FUNCTION__));
+
          return FALSE;
       }
    }
@@ -1651,7 +1669,8 @@ HgfsAddToCacheInternal(HgfsHandle handle,         // IN: HGFS file handle
  *    file descriptor. If the node was not already in the cache then nothing
  *    is done.
  *
- *    The session's nodeArrayLock should be acquired prior to calling this function.
+ *    The session's nodeArrayLock should be acquired prior to calling this
+ *    function.
  *
  * Results:
  *    TRUE on success
@@ -1673,7 +1692,8 @@ HgfsRemoveFromCacheInternal(HgfsHandle handle,        // IN: Hgfs handle to the
 
    node = HgfsHandle2FileNode(handle, session);
    if (node == NULL) {
-      LOG(4, ("HgfsRemoveFromCacheInternal: invalid handle.\n"));
+      LOG(4, ("%s: invalid handle.\n", __FUNCTION__));
+
       return FALSE;
    }
 
@@ -1694,9 +1714,10 @@ HgfsRemoveFromCacheInternal(HgfsHandle handle,        // IN: Hgfs handle to the
        * Instead, we'll just await the lobotomization of the node cache to
        * really fix this.
        */
+
       if (HgfsCloseFile(node->fileDesc)) {
-         LOG(4, ("HgfsRemoveFromCacheInternal: Could not close fd %u\n",
-                 node->fileDesc));
+         LOG(4, ("%s: Could not close fd %u\n", __FUNCTION__, node->fileDesc));
+
          return FALSE;
       }
 
@@ -1745,15 +1766,19 @@ HgfsIsCachedInternal(HgfsHandle handle,         // IN: Structure representing fi
 
    node = HgfsHandle2FileNode(handle, session);
    if (node == NULL) {
-      LOG(4, ("HgfsIsCachedInternal: invalid handle.\n"));
+      LOG(4, ("%s: invalid handle.\n", __FUNCTION__));
+
       return FALSE;
    }
+
    if (node->state == FILENODE_STATE_IN_USE_CACHED) {
       /*
        * Move this node to the end of the list.
        */
+
       DblLnkLst_Unlink1(&node->links);
       DblLnkLst_LinkLast(&session->nodeCachedList, &node->links);
+
       return TRUE;
    }
 
@@ -1790,6 +1815,7 @@ HgfsIsServerLockAllowed(HgfsSessionInfo *session)  // IN: session info
    SyncMutex_Lock(&session->nodeArrayLock);
    allowed = session->numCachedLockedNodes < MAX_LOCKED_FILENODES;
    SyncMutex_Unlock(&session->nodeArrayLock);
+
    return allowed;
 }
 
@@ -1829,13 +1855,14 @@ HgfsGetNewSearch(HgfsSessionInfo *session)  // IN: session info
    ASSERT(session);
    ASSERT(session->searchArray);
 
-   LOG(4, ("HgfsGetNewSearch: entered\n"));
+   LOG(4, ("%s: entered\n", __FUNCTION__));
 
    if (!DblLnkLst_IsLinked(&session->searchFreeList)) {
       /*
        * This has to be unsigned and with maximum bit length. This is
        * required to take care of "negative" differences as well.
        */
+
       uintptr_t ptrDiff;
 
       if (DOLOG(4)) {
@@ -1848,7 +1875,8 @@ HgfsGetNewSearch(HgfsSessionInfo *session)  // IN: session info
       newMem = (HgfsSearch *)realloc(session->searchArray,
                                      newNumSearches * sizeof *(session->searchArray));
       if (!newMem) {
-         LOG(4, ("HgfsGetNewSearch: can't realloc more searches\n"));
+         LOG(4, ("%s: can't realloc more searches\n", __FUNCTION__));
+
          return NULL;
       }
 
@@ -1862,14 +1890,14 @@ HgfsGetNewSearch(HgfsSessionInfo *session)  // IN: session info
           * must be updated to point to the new portion of memory.
           */
 
-         LOG(4, ("Rebasing pointers, diff is %"FMTSZ"u, sizeof search is %"FMTSZ"u\n",
-                 ptrDiff, sizeof(HgfsSearch)));
+         LOG(4, ("Rebasing pointers, diff is %"FMTSZ"u, sizeof search is "
+                 "%"FMTSZ"u\n", ptrDiff, sizeof(HgfsSearch)));
          LOG(4, ("old: %p new: %p\n", session->searchArray, newMem));
          ASSERT(newMem == (HgfsSearch*)((char*)session->searchArray + ptrDiff));
 
-#define HgfsServerRebase(_ptr, _type)                                            \
-   if ((size_t)((char *)_ptr - (char *)session->searchArray) < oldSize) {        \
-      _ptr = (_type *)((char *)_ptr + ptrDiff);                                  \
+#define HgfsServerRebase(_ptr, _type)                                     \
+   if ((size_t)((char *)_ptr - (char *)session->searchArray) < oldSize) { \
+      _ptr = (_type *)((char *)_ptr + ptrDiff);                           \
    }
 
          /*
@@ -1890,7 +1918,9 @@ HgfsGetNewSearch(HgfsSessionInfo *session)  // IN: session info
       }
 
       /* Initialize the new searches */
-      LOG(4, ("numSearches was %u, now is %u\n", session->numSearches, newNumSearches));
+      LOG(4, ("numSearches was %u, now is %u\n", session->numSearches,
+               newNumSearches));
+
       for (i = session->numSearches; i < newNumSearches; i++) {
          DblLnkLst_Init(&newMem[i].links);
          newMem[i].utf8Dir = NULL;
@@ -2011,6 +2041,7 @@ HgfsGetSearchCopy(HgfsHandle handle,        // IN: Hgfs search handle
 
 exit:
    SyncMutex_Unlock(&session->searchArrayLock);
+
    return found;
 }
 
@@ -2048,7 +2079,8 @@ HgfsAddNewSearch(char const *utf8Dir,       // IN: UTF8 name of dir to search in
    /* Get an unused search */
    newSearch = HgfsGetNewSearch(session);
    if (!newSearch) {
-      LOG(4, ("HgfsAddNewSearch: out of memory\n"));
+      LOG(4, ("%s: out of memory\n", __FUNCTION__));
+
       return NULL;
    }
 
@@ -2061,6 +2093,7 @@ HgfsAddNewSearch(char const *utf8Dir,       // IN: UTF8 name of dir to search in
    newSearch->utf8Dir = strdup(utf8Dir);
    if (newSearch->utf8Dir == NULL) {
       HgfsRemoveSearchInternal(newSearch, session);
+
       return NULL;
    }
 
@@ -2068,11 +2101,13 @@ HgfsAddNewSearch(char const *utf8Dir,       // IN: UTF8 name of dir to search in
    newSearch->utf8ShareName = strdup(utf8ShareName);
    if (newSearch->utf8ShareName == NULL) {
       HgfsRemoveSearchInternal(newSearch, session);
+
       return NULL;
    }
 
-   LOG(4, ("HgfsAddNewSearch: got new search, handle %u\n",
+   LOG(4, ("%s: got new search, handle %u\n", __FUNCTION__,
            HgfsSearch2SearchHandle(newSearch)));
+
    return newSearch;
 }
 
@@ -2102,7 +2137,7 @@ HgfsRemoveSearchInternal(HgfsSearch *search,       // IN: search
    ASSERT(search);
    ASSERT(session);
 
-   LOG(4, ("HgfsRemoveSearchInternal: handle %u, dir %s\n",
+   LOG(4, ("%s: handle %u, dir %s\n", __FUNCTION__,
            HgfsSearch2SearchHandle(search), search->utf8Dir));
 
    /* Free all of the dirents */
@@ -2239,6 +2274,7 @@ HgfsGetSearchResult(HgfsHandle handle,         // IN: Handle to search
        * at the top of hgfsServerInt.h, you'll see that on Windows we only
        * define d_reclen and d_name, as those are the only fields we need.
        */
+
       dent->d_reclen = originalDent->d_reclen;
       memcpy(dent->d_name, originalDent->d_name, nameLen);
       dent->d_name[nameLen] = 0;
@@ -2246,6 +2282,7 @@ HgfsGetSearchResult(HgfsHandle handle,         // IN: Handle to search
 
   out:
    SyncMutex_Unlock(&session->searchArrayLock);
+
    return dent;
 }
 
@@ -2340,7 +2377,7 @@ HgfsUpdateNodeNames(const char *oldLocalName,  // IN: Name of file to look for
       if (strcmp(fileNode->utf8Name, oldLocalName) == 0) {
          newBuffer = malloc(newBufferLen + 1);
          if (!newBuffer) {
-            LOG(4, ("HgfsUpdateNodeNames: Failed to update a node name.\n"));
+            LOG(4, ("%s: Failed to update a node name.\n", __FUNCTION__));
             continue;
          }
          memcpy(newBuffer, newLocalName, newBufferLen);
@@ -2401,14 +2438,14 @@ HgfsServerClose(char const *packetIn,      // IN: incoming packet
       HgfsRequestClose *request;
       request = (HgfsRequestClose *)packetIn;
       file = &request->file;
-      replySize = sizeof *request;
+      replySize = sizeof (HgfsReplyClose);
       packetOut = Util_SafeMalloc(replySize);
    }
 
-   LOG(4, ("HgfsServerClose: close fh %u\n", *file));
+   LOG(4, ("%s: close fh %u\n", __FUNCTION__, *file));
 
    if (!HgfsRemoveFromCache(*file, session)) {
-      LOG(4, ("HgfsServerClose: Could not remove the node from cache.\n"));
+      LOG(4, ("%s: Could not remove the node from cache.\n", __FUNCTION__));
       status = HGFS_INTERNAL_STATUS_ERROR;
       goto error;
    } else {
@@ -2420,10 +2457,12 @@ HgfsServerClose(char const *packetIn,      // IN: incoming packet
    if (!HgfsPacketSend(packetOut, replySize, session, 0)) {
       goto error;
    }
+
    return 0;
 
 error:
    free(packetOut);
+
    return status;
 }
 
@@ -2481,11 +2520,11 @@ HgfsServerSearchClose(char const *packetIn,      // IN: incoming packet
       search = &request->search;
    }
 
-   LOG(4, ("HgfsServerSearchClose: close search #%u\n", *search));
+   LOG(4, ("%s: close search #%u\n", __FUNCTION__, *search));
 
    if (!HgfsRemoveSearch(*search, session)) {
       /* Invalid handle */
-      LOG(4, ("HgfsServerSearchClose: invalid handle %u\n", *search));
+      LOG(4, ("%s: invalid handle %u\n", __FUNCTION__, *search));
       status = HGFS_INTERNAL_STATUS_ERROR;
       goto error;
    }
@@ -2495,10 +2534,12 @@ HgfsServerSearchClose(char const *packetIn,      // IN: incoming packet
    if (!HgfsPacketSend(packetOut, replySize, session, 0)) {
       goto error;
    }
+
    return 0;
 
 error:
    free(packetOut);
+
    return status;
 }
 
@@ -2605,7 +2646,9 @@ HgfsServerSessionReceive(char const *packetIn,    // IN: incoming packet
    ASSERT(request);
 
    if (session->state == HGFS_SESSION_STATE_CLOSED) {
-      LOG(4, ("%s: %d: Received packet after disconnected.\n", __FUNCTION__, __LINE__));
+      LOG(4, ("%s: %d: Received packet after disconnected.\n", __FUNCTION__,
+              __LINE__));
+
       return;
    }
 
@@ -2625,8 +2668,7 @@ HgfsServerSessionReceive(char const *packetIn,    // IN: incoming packet
    if (op < sizeof handlers / sizeof handlers[0]) {
       if (packetSize >= handlers[op].minReqSize) {
          HgfsInternalStatus internalStatus;
-         internalStatus = (*handlers[op].handler)(packetIn,
-                                                  packetSize,
+         internalStatus = (*handlers[op].handler)(packetIn, packetSize,
                                                   session);
          status = HgfsConvertFromInternalStatus(internalStatus);
       } else {
@@ -2634,13 +2676,16 @@ HgfsServerSessionReceive(char const *packetIn,    // IN: incoming packet
           * The input packet is smaller than the minimal size needed for the
           * operation.
           */
+
          status = HGFS_STATUS_PROTOCOL_ERROR;
-         LOG(4, ("%s: %d: Possible BUG! Smaller packet.\n", __FUNCTION__, __LINE__));
+         LOG(4, ("%s: %d: Possible BUG! Smaller packet.\n", __FUNCTION__,
+                 __LINE__));
       }
    } else {
       /* Unknown opcode */
       status = HGFS_STATUS_PROTOCOL_ERROR;
-      LOG(4, ("%s: %d: Possible BUG! Invalid opcode.\n", __FUNCTION__, __LINE__));
+      LOG(4, ("%s: %d: Possible BUG! Invalid opcode.\n", __FUNCTION__,
+              __LINE__));
    }
    HGFS_ASSERT_CLIENT(op);
 
@@ -2708,10 +2753,12 @@ HgfsServer_InitState(HgfsServerSessionCallbacks **callbackTable,  // IN/OUT: our
 
    if (!HgfsServerPlatformInit()) {
       LOG(4, ("Could not initialize server platform specific \n"));
+
       return FALSE;
    }
 
    *callbackTable = &hgfsServerSessionCBTable;
+
    return TRUE;
 }
 
@@ -2788,15 +2835,18 @@ HgfsServerSessionConnect(void *transportData,        // IN: transport session co
    /*
     * Initialize all our locks first as these can fail.
     */
+
    if (!SyncMutex_Init(&session->fileIOLock, NULL)) {
       free(session);
       LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
+
       return FALSE;
    }
    if (!SyncMutex_Init(&session->nodeArrayLock, NULL)) {
       SyncMutex_Destroy(&session->fileIOLock);
       free(session);
       LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
+
       return FALSE;
    }
    if (!SyncMutex_Init(&session->searchArrayLock, NULL)) {
@@ -2804,18 +2854,20 @@ HgfsServerSessionConnect(void *transportData,        // IN: transport session co
       SyncMutex_Destroy(&session->nodeArrayLock);
       free(session);
       LOG(4, ("%s: Could not create search array sync mutex.\n", __FUNCTION__));
+
       return FALSE;
    }
 
    /*
     * Initialize the node handling components.
     */
+
    DblLnkLst_Init(&session->nodeFreeList);
    DblLnkLst_Init(&session->nodeCachedList);
 
    /* Allocate array of FileNodes and add them to free list. */
    session->numNodes = NUM_FILE_NODES;
-   session->nodeArray = Util_SafeCalloc(session->numNodes, sizeof(HgfsFileNode));
+   session->nodeArray = Util_SafeCalloc(session->numNodes, sizeof (HgfsFileNode));
    session->numCachedOpenNodes = 0;
    session->numCachedLockedNodes = 0;
 
@@ -2834,17 +2886,19 @@ HgfsServerSessionConnect(void *transportData,        // IN: transport session co
 
    /* Allocate array of searches and add them to free list. */
    session->numSearches = NUM_SEARCHES;
-   session->searchArray = Util_SafeCalloc(session->numSearches, sizeof(HgfsSearch));
+   session->searchArray = Util_SafeCalloc(session->numSearches, sizeof (HgfsSearch));
 
    for (i = 0; i < session->numSearches; i++) {
       DblLnkLst_Init(&session->searchArray[i].links);
       /* Append at the end of the list. */
-      DblLnkLst_LinkLast(&session->searchFreeList, &session->searchArray[i].links);
+      DblLnkLst_LinkLast(&session->searchFreeList,
+                         &session->searchArray[i].links);
    }
 
    /*
     * Initialize the general session stuff.
     */
+
    session->type = HGFS_SESSION_TYPE_REGULAR;
    session->state = HGFS_SESSION_STATE_OPEN;
    session->transportData = transportData;
@@ -2854,6 +2908,7 @@ HgfsServerSessionConnect(void *transportData,        // IN: transport session co
    /* Give our session a reference to hold while we are open. */
    HgfsServerSessionGet(session);
    *sessionData = session;
+
    return TRUE;
 }
 
@@ -2956,7 +3011,6 @@ HgfsServerExitSessionInternal(HgfsSessionInfo *session)    // IN: session contex
    ASSERT(session->nodeArray);
    ASSERT(session->searchArray);
 
-
    SyncMutex_Lock(&session->nodeArrayLock);
 
    LOG(4, ("%s: exiting.\n", __FUNCTION__));
@@ -3086,9 +3140,12 @@ HgfsServer_ProcessPacket(char const *packetIn,   // IN: incoming packet
     * Create the session if not already created.
     * This session is destroyed in HgfsServer_ExitState.
     */
+
    if (hgfsStaticSession.session == NULL) {
-      if (!HgfsServerSessionConnect(NULL, NULL, (void **)&hgfsStaticSession.session)) {
+      if (!HgfsServerSessionConnect(NULL, NULL,
+                                    (void **)&hgfsStaticSession.session)) {
          *packetLen = 0;
+
          return;
       }
 
@@ -3103,9 +3160,11 @@ HgfsServer_ProcessPacket(char const *packetIn,   // IN: incoming packet
     * we should have the reply by now.
     * XXX This should change if any async replies are expected.
     */
+
    ASSERT(hgfsStaticSession.bufferOut);
 
-   memcpy(packetOut, hgfsStaticSession.bufferOut, hgfsStaticSession.bufferOutLen);
+   memcpy(packetOut, hgfsStaticSession.bufferOut,
+          hgfsStaticSession.bufferOutLen);
    *packetLen = hgfsStaticSession.bufferOutLen;
 
    HgfsServerSessionSendComplete(hgfsStaticSession.session,
@@ -3182,6 +3241,7 @@ HgfsPacketSend(char *packet,                // IN: packet buffer
    }
 
    HgfsServerSessionPut(session);
+
    return result;
 }
 
@@ -3259,6 +3319,7 @@ HgfsServerCheckPathPrefix(const char *path,  // IN: Path to check
     * by a second path separator. In this case, no additional checks besides the
     * initial prefix check are needed. Just return success.
     */
+
    if (shareLen == 1 && *share == DIRSEPC) {
       return TRUE;
    }
@@ -3319,6 +3380,7 @@ HgfsInvalidateSessionObjects(DblLnkLst_Links *shares,  // IN: List of new shares
     * Iterate over each node, skipping those that are unused. For each node,
     * if its filename is no longer within a share, remove it.
     */
+
    for (i = 0; i < session->numNodes; i++) {
       HgfsHandle handle;
       DblLnkLst_Links *l;
@@ -3365,6 +3427,7 @@ HgfsInvalidateSessionObjects(DblLnkLst_Links *shares,  // IN: List of new shares
     * Iterate over each search, skipping those that are on the free list. For
     * each search, if its base name is no longer within a share, remove it.
     */
+
    for (i = 0; i < session->numSearches; i++) {
       HgfsHandle handle;
       DblLnkLst_Links *l;
@@ -3384,8 +3447,7 @@ HgfsInvalidateSessionObjects(DblLnkLst_Links *shares,  // IN: List of new shares
          share = DblLnkLst_Container(l, HgfsSharedFolder, links);
          ASSERT(share);
          if (HgfsServerCheckPathPrefix(session->searchArray[i].utf8Dir,
-                                       share->path,
-                                       share->pathLen)) {
+                                       share->path, share->pathLen)) {
             LOG(4, ("%s: Search is still valid\n", __FUNCTION__));
             break;
          }
@@ -3480,8 +3542,10 @@ HgfsServerStatFs(const char *pathName, // IN: Path we're interested in
     * delimiter on copy. Allow 0 length drives so that hidden feature "" can
     * work.
     */
+
    if (pathLength < 0 || pathLength >= sizeof p.mountPoint) {
-      LOG(4, ("HgfsServerStatFs: could not get the volume name\n"));
+      LOG(4, ("%s: could not get the volume name\n", __FUNCTION__));
+
       return FALSE;
    }
 
@@ -3489,8 +3553,8 @@ HgfsServerStatFs(const char *pathName, // IN: Path we're interested in
    Str_Strcpy(p.mountPoint, pathName, sizeof p.mountPoint);
    wiperError = WiperSinglePartition_GetSpace(&p, freeBytes, totalBytes);
    if (strlen(wiperError) > 0) {
-      LOG(4, ("HgfsServerQueryVolume: error using wiper lib: %s\n",
-              wiperError));
+      LOG(4, ("%s: error using wiper lib: %s\n", __FUNCTION__, wiperError));
+
       return FALSE;
    }
 
@@ -3556,7 +3620,8 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
     */
    len = CPName_GetComponent(cpName, inEnd, (char const **) &next);
    if (len < 0) {
-      LOG(4, ("HgfsServerGetAccess: get first component failed\n"));
+      LOG(4, ("%s: get first component failed\n", __FUNCTION__));
+
       return HGFS_NAME_STATUS_FAILURE;
    }
 
@@ -3566,21 +3631,20 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
    }
 
    /* Check permission on the share and get the share path */
-   nameStatus = HgfsServerPolicy_GetSharePath(cpName,
-                                              len,
-                                              mode,
-                                              &sharePathLen,
+   nameStatus = HgfsServerPolicy_GetSharePath(cpName, len, mode, &sharePathLen,
                                               &sharePath);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsServerGetAccess: No such share (%s) or access denied\n",
+      LOG(4, ("%s: No such share (%s) or access denied\n", __FUNCTION__,
               cpName));
+
       return nameStatus;
    }
 
    /* Get the config options. */
    nameStatus = HgfsServerPolicy_GetShareOptions(cpName, len, &shareOptions);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsServerGetAccess: no matching share: %s.\n", cpName));
+      LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, cpName));
+
       return nameStatus;
    }
 
@@ -3591,10 +3655,12 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
    /*
     * Allocate space for the string. We trim the unused space later.
     */
+
    outSize = HGFS_PATH_MAX;
-   myBufOut = (char *)malloc(outSize * sizeof *myBufOut);
+   myBufOut = (char *) malloc(outSize * sizeof *myBufOut);
    if (!myBufOut) {
-      LOG(4, ("HgfsServerGetAccess: out of memory allocating string\n"));
+      LOG(4, ("%s: out of memory allocating string\n", __FUNCTION__));
+
       return HGFS_NAME_STATUS_OUT_OF_MEMORY;
    }
 
@@ -3603,6 +3669,7 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
    /*
     * See if we are dealing with a "root" share or regular share
     */
+
    if (strlen(sharePath) == 0) {
       size_t prefixLen;
 
@@ -3612,14 +3679,13 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
        * buffer (for Win32) or simply get the prefix for root (for
        * linux).
        */
+
       tempSize = sizeof tempBuf;
       tempPtr = tempBuf;
       nameStatus = CPName_ConvertFromRoot((char const **) &cpName,
-                                          &cpNameSize,
-                                          &tempSize,
-                                          &tempPtr);
+                                          &cpNameSize, &tempSize, &tempPtr);
       if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-         LOG(4, ("HgfsServerGetAccess: ConvertFromRoot not complete\n"));
+         LOG(4, ("%s: ConvertFromRoot not complete\n", __FUNCTION__));
          goto error;
       }
 
@@ -3627,7 +3693,7 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
 
       /* Copy the UTF8 prefix to the output buffer. */
       if (prefixLen >= HGFS_PATH_MAX) {
-         Log("HgfsServerGetAccess: error: prefix too long\n");
+         Log("%s: error: prefix too long\n", __FUNCTION__);
          nameStatus = HGFS_NAME_STATUS_TOO_LONG;
          goto error;
       }
@@ -3640,8 +3706,9 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
       /*
        * This is a regular share. Append the path to the out buffer.
        */
+
       if (outSize < sharePathLen + 1) {
-         LOG(4, ("HgfsServerGetAccess: share path too big\n"));
+         LOG(4, ("%s: share path too big\n", __FUNCTION__));
          nameStatus = HGFS_NAME_STATUS_TOO_LONG;
          goto error;
       }
@@ -3656,11 +3723,9 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
    tempPtr = tempBuf;
 
 
-   if (CPName_ConvertFrom((char const **) &cpName,
-                          &cpNameSize,
-                          &tempSize,
+   if (CPName_ConvertFrom((char const **) &cpName, &cpNameSize, &tempSize,
                           &tempPtr) < 0) {
-      LOG(4, ("HgfsServerGetAccess: CP name conversion failed\n"));
+      LOG(4, ("%s: CP name conversion failed\n", __FUNCTION__));
       nameStatus = HGFS_NAME_STATUS_FAILURE;
       goto error;
    }
@@ -3670,16 +3735,15 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
     * separator and since our remaining paths start with a separator, we
     * will skip over the second separator for this case. Bug 166755.
     */
-   if ((out != myBufOut) &&
-       (*(out - 1) == DIRSEPC) &&
-       (tempBuf[0] == DIRSEPC)) {
+
+   if ((out != myBufOut) && (*(out - 1) == DIRSEPC) && (tempBuf[0] == DIRSEPC)) {
       startIndex++;
    }
    pathNameLen = tempPtr - &tempBuf[startIndex];
 
    /* Copy UTF8 to the output buffer. */
    if (pathNameLen >= outSize) {
-      LOG(4, ("HgfsServerGetAccess: pathname too long\n"));
+      LOG(4, ("%s: pathname too long\n", __FUNCTION__));
       nameStatus = HGFS_NAME_STATUS_TOO_LONG;
       goto error;
    }
@@ -3698,17 +3762,16 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
        * so there is a need to convert the incoming name from HGFS clients
        * which is assumed to be in the normalized form C (precomposed).
        */
-      if (!CodeSet_Utf8FormCToUtf8FormD(myBufOut,
-                                        myBufOutLen,
-                                        &tempPtr,
+
+      if (!CodeSet_Utf8FormCToUtf8FormD(myBufOut, myBufOutLen, &tempPtr,
                                         &nameLen)) {
-         LOG(4, ("HgfsServerGetAccess: unicode conversion to form D failed.\n"));
+         LOG(4, ("%s: unicode conversion to form D failed.\n", __FUNCTION__));
          nameStatus = HGFS_NAME_STATUS_FAILURE;
          goto error;
       }
 
       free(myBufOut);
-      LOG(4, ("HgfsServerGetAccess: name is \"%s\"\n", myBufOut));
+      LOG(4, ("%s: name is \"%s\"\n", __FUNCTION__, myBufOut));
 
       /* Save returned pointers, update buffer length. */
       myBufOut = tempPtr;
@@ -3721,17 +3784,21 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
     * Convert file name to proper case if host default config option is not set
     * and case conversion is required for this platform.
     */
-   if (!HgfsServerPolicy_IsShareOptionSet(shareOptions, HGFS_SHARE_HOST_DEFAULT_CASE) &&
+
+   if (!HgfsServerPolicy_IsShareOptionSet(shareOptions,
+                                          HGFS_SHARE_HOST_DEFAULT_CASE) &&
        HgfsServerCaseConversionRequired()) {
       nameStatus = HgfsServerConvertCase(sharePath, sharePathLen, myBufOut,
                                          myBufOutLen, caseFlags,
-                                         &convertedMyBufOut, &convertedMyBufOutLen);
+                                         &convertedMyBufOut,
+                                         &convertedMyBufOutLen);
 
       /*
        * On success, use the converted file names for further operations.
        */
+
       if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-         LOG(4, ("HgfsServerGetAccess: HgfsServerConvertCase failed.\n"));
+         LOG(4, ("%s: HgfsServerConvertCase failed.\n", __FUNCTION__));
          goto error;
       }
 
@@ -3742,19 +3809,22 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
    }
 
    /* Check for symlinks if the followSymlinks option is not set. */
-   if (!HgfsServerPolicy_IsShareOptionSet(shareOptions, HGFS_SHARE_FOLLOW_SYMLINKS)) {
+   if (!HgfsServerPolicy_IsShareOptionSet(shareOptions,
+                                          HGFS_SHARE_FOLLOW_SYMLINKS)) {
       /*
        * Verify that either the path is same as share path or the path until the
        * parent directory is within the share.
        *
-       * XXX: Symlink check could become susceptible to TOCTOU (time-of-check, time-of-use)
-       * attack when we move to asynchrounous HGFS operations. We should use the resolved
-       * file path for further file system operations, instead of using the one passed
-       * from the client.
+       * XXX: Symlink check could become susceptible to TOCTOU (time-of-check,
+       * time-of-use) attack when we move to asynchrounous HGFS operations.
+       * We should use the resolved file path for further file system
+       * operations, instead of using the one passed from the client.
        */
-      nameStatus = HgfsServerHasSymlink(myBufOut, myBufOutLen, sharePath, sharePathLen);
+
+      nameStatus = HgfsServerHasSymlink(myBufOut, myBufOutLen, sharePath,
+                                        sharePathLen);
       if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-         LOG(4, ("HgfsServerGetAccess: parent path failed to be resolved: %d\n",
+         LOG(4, ("%s: parent path failed to be resolved: %d\n", __FUNCTION__,
                  nameStatus));
          goto error;
       }
@@ -3768,7 +3838,7 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
       /* Enough space for resulting string + NUL termination */
       p = realloc(myBufOut, (myBufOutLen + 1) * sizeof *p);
       if (!p) {
-         LOG(4, ("HgfsServerGetAccess: failed to trim memory\n"));
+         LOG(4, ("%s: failed to trim memory\n", __FUNCTION__));
       } else {
          myBufOut = p;
       }
@@ -3778,13 +3848,15 @@ HgfsServerGetAccess(char *cpName,                  // IN:  Cross-platform filena
       }
    }
 
-   LOG(4, ("HgfsServerGetAccess: name is \"%s\"\n", myBufOut));
+   LOG(4, ("%s: name is \"%s\"\n", __FUNCTION__, myBufOut));
 
    *bufOut = myBufOut;
+
    return HGFS_NAME_STATUS_COMPLETE;
 
 error:
    free(myBufOut);
+
    return nameStatus;
 }
 
@@ -3823,6 +3895,7 @@ HgfsServerIsSharedFolderOnly(char const *cpName,// IN:  Cross-platform filename
 
    len = CPName_GetComponent(cpName, inEnd, &next);
    ASSERT(len > 0);
+
    return (next == inEnd);
 }
 
@@ -3854,8 +3927,9 @@ HgfsServerDumpDents(HgfsHandle searchHandle,  // IN: Handle to dump dents from
    SyncMutex_Lock(&session->searchArrayLock);
    search = HgfsSearchHandle2Search(searchHandle, session);
    if (search != NULL) {
-      Log("HgfsServerDumpDents: %u dents in \"%s\"\n",
-          search->numDents, search->utf8Dir);
+      Log("%s: %u dents in \"%s\"\n", __FUNCTION__, search->numDents,
+          search->utf8Dir);
+
       Log("Dumping dents:\n");
       for (i = 0; i < search->numDents; i++) {
          Log("\"%s\"\n", search->dents[i]->d_name);
@@ -3898,7 +3972,7 @@ HgfsServerGetDents(HgfsGetNameFunc getName,     // IN: Function to get name
 
    state = initName();
    if (!state) {
-      LOG(4, ("HgfsServerGetDents: Couldn't init state\n"));
+      LOG(4, ("%s: Couldn't init state\n", __FUNCTION__));
       goto error_free;
    }
 
@@ -3919,13 +3993,13 @@ HgfsServerGetDents(HgfsGetNameFunc getName,     // IN: Function to get name
          len = 2;
       } else {
          if (!getName(state, &name, &len, &done)) {
-            LOG(4, ("HgfsServerGetDents: Couldn't get next name\n"));
+            LOG(4, ("%s: Couldn't get next name\n", __FUNCTION__));
             goto error;
          }
       }
 
       if (done) {
-         LOG(4, ("HgfsServerGetDents: No more names\n"));
+         LOG(4, ("%s: No more names\n", __FUNCTION__));
          break;
       }
 
@@ -3936,12 +4010,13 @@ HgfsServerGetDents(HgfsGetNameFunc getName,     // IN: Function to get name
        * our purposes, so we use PATH_MAX as a reasonable upper bound on the
        * length of the name.
        */
+
       maxLen = PATH_MAX;
 #else
       maxLen = sizeof pDirEntry->d_name;
 #endif
       if (len >= maxLen) {
-         Log("HgfsServerGetDents: Error: Name \"%s\" is too long.\n", name);
+         Log("%s: Error: Name \"%s\" is too long.\n", __FUNCTION__, name);
          continue;
       }
 
@@ -3956,25 +4031,25 @@ HgfsServerGetDents(HgfsGetNameFunc getName,     // IN: Function to get name
          }
          p = realloc(myDents, totalDents * sizeof *myDents);
          if (!p) {
-            LOG(4, ("HgfsServerGetDents: Couldn't reallocate array memory\n"));
+            LOG(4, ("%s: Couldn't reallocate array memory\n", __FUNCTION__));
             goto error;
          }
          myDents = (DirectoryEntry **)p;
       }
 
       /* This file/directory can be added to the list. */
-      LOG(4, ("HgfsServerGetDents: Nextfilename = \"%s\"\n", name));
+      LOG(4, ("%s: Nextfilename = \"%s\"\n", __FUNCTION__, name));
 
       /*
        * Start with the size of the DirectoryEntry struct, subtract the static
-       * length of the d_name buffer (256 in Linux, 1 in Solaris, etc) and add back
-       * just enough space for the UTF-8 name and nul terminator.
+       * length of the d_name buffer (256 in Linux, 1 in Solaris, etc) and add
+       * back just enough space for the UTF-8 name and nul terminator.
        */
-      newDirEntryLen =
-         sizeof *pDirEntry - sizeof pDirEntry->d_name + len + 1;
+
+      newDirEntryLen = sizeof *pDirEntry - sizeof pDirEntry->d_name + len + 1;
       pDirEntry = (DirectoryEntry *)malloc(newDirEntryLen);
       if (!pDirEntry) {
-         LOG(4, ("HgfsServerGetDents: Couldn't allocate dentry memory\n"));
+         LOG(4, ("%s: Couldn't allocate dentry memory\n", __FUNCTION__));
          goto error;
       }
       pDirEntry->d_reclen = (unsigned short)newDirEntryLen;
@@ -3987,7 +4062,7 @@ HgfsServerGetDents(HgfsGetNameFunc getName,     // IN: Function to get name
 
    /* We are done; cleanup the state */
    if (!cleanupName(state)) {
-      LOG(4, ("HgfsServerGetDents: Non-error cleanup failed\n"));
+      LOG(4, ("%s: Non-error cleanup failed\n", __FUNCTION__));
       goto error_free;
    }
 
@@ -3997,7 +4072,7 @@ HgfsServerGetDents(HgfsGetNameFunc getName,     // IN: Function to get name
 
       p = realloc(myDents, numDents * sizeof *myDents);
       if (!p) {
-         LOG(4, ("HgfsServerGetDents: Couldn't realloc less array memory\n"));
+         LOG(4, ("%s: Couldn't realloc less array memory\n", __FUNCTION__));
          *dents = myDents;
       } else {
          *dents = (DirectoryEntry **)p;
@@ -4009,7 +4084,7 @@ HgfsServerGetDents(HgfsGetNameFunc getName,     // IN: Function to get name
 error:
    /* Cleanup the callback state */
    if (!cleanupName(state)) {
-      LOG(4, ("HgfsServerGetDents: Error cleanup failed\n"));
+      LOG(4, ("%s: Error cleanup failed\n", __FUNCTION__));
    }
 
 error_free:
@@ -4075,7 +4150,7 @@ HgfsServerSearchRealDir(char const *baseDir,      // IN: Directory to search
    SyncMutex_Lock(&session->searchArrayLock);
    search = HgfsAddNewSearch(baseDir, type, shareName, session);
    if (!search) {
-      LOG(4, ("HgfsServerSearchRealDir: failed to get new search\n"));
+      LOG(4, ("%s: failed to get new search\n", __FUNCTION__));
       status = HGFS_INTERNAL_STATUS_ERROR;
       goto out;
    }
@@ -4084,7 +4159,7 @@ HgfsServerSearchRealDir(char const *baseDir,      // IN: Directory to search
    nameStatus = HgfsServerPolicy_GetShareOptions(shareName, strlen(shareName),
                                                  &configOptions);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsServerSearchRealDir: no matching share: %s.\n", shareName));
+      LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, shareName));
       status = HGFS_INTERNAL_STATUS_ERROR;
       HgfsRemoveSearchInternal(search, session);
       goto out;
@@ -4096,15 +4171,17 @@ HgfsServerSearchRealDir(char const *baseDir,      // IN: Directory to search
    status = HgfsServerScandir(baseDir, baseDirLen, followSymlinks,
                               &search->dents, &numDents);
    if (status != 0) {
-      LOG(4, ("HgfsServerSearchRealDir: couldn't scandir\n"));
+      LOG(4, ("%s: couldn't scandir\n", __FUNCTION__));
       HgfsRemoveSearchInternal(search, session);
       goto out;
    }
 
    search->numDents = numDents;
    *handle = HgfsSearch2SearchHandle(search);
+
   out:
    SyncMutex_Unlock(&session->searchArrayLock);
+
    return status;
 }
 
@@ -4149,17 +4226,14 @@ HgfsServerSearchVirtualDir(HgfsGetNameFunc *getName,     // IN: Name enumerator
    SyncMutex_Lock(&session->searchArrayLock);
    search = HgfsAddNewSearch("", type, "", session);
    if (!search) {
-      LOG(4, ("HgfsServerSearchVirtualDir: failed to get new search\n"));
+      LOG(4, ("%s: failed to get new search\n", __FUNCTION__));
       status = HGFS_INTERNAL_STATUS_ERROR;
       goto out;
    }
 
-   result = HgfsServerGetDents(getName,
-                               initName,
-                               cleanupName,
-                               &search->dents);
+   result = HgfsServerGetDents(getName, initName, cleanupName, &search->dents);
    if (result < 0) {
-      LOG(4, ("HgfsServerSearchVirtualDir: couldn't get dents\n"));
+      LOG(4, ("%s: couldn't get dents\n", __FUNCTION__));
       HgfsRemoveSearchInternal(search, session);
       status = HGFS_INTERNAL_STATUS_ERROR;
       goto out;
@@ -4167,8 +4241,10 @@ HgfsServerSearchVirtualDir(HgfsGetNameFunc *getName,     // IN: Name enumerator
 
    search->numDents = result;
    *handle = HgfsSearch2SearchHandle(search);
+
   out:
    SyncMutex_Unlock(&session->searchArrayLock);
+
    return status;
 }
 
@@ -4197,6 +4273,7 @@ HgfsRemoveFromCache(HgfsHandle handle,          // IN: Hgfs handle to the node
                     HgfsSessionInfo *session) // IN: Session info
 {
    Bool removed = FALSE;
+
    SyncMutex_Lock(&session->nodeArrayLock);
    removed = HgfsRemoveFromCacheInternal(handle, session);
    SyncMutex_Unlock(&session->nodeArrayLock);
@@ -4252,7 +4329,8 @@ HgfsIsCached(HgfsHandle handle,         // IN: Structure representing file node
  *
  *    Assumes that there is at least one node in the cache.
  *
- *    The session's nodeArrayLock should be acquired prior to calling this function.
+ *    The session's nodeArrayLock should be acquired prior to calling this
+ *    function.
  *
  * Results:
  *    TRUE on success
@@ -4276,7 +4354,9 @@ HgfsRemoveLruNode(HgfsSessionInfo *session)   // IN: session info
 
    /* Remove the first item from the list that does not have a server lock. */
    while (!found) {
-      lruNode = DblLnkLst_Container(session->nodeCachedList.next, HgfsFileNode, links);
+      lruNode = DblLnkLst_Container(session->nodeCachedList.next,
+                                    HgfsFileNode, links);
+
       ASSERT(lruNode->state == FILENODE_STATE_IN_USE_CACHED);
       if (lruNode->serverLock != HGFS_LOCK_NONE) {
          /* Move this node with the server lock to the beginning of the list. */
@@ -4288,7 +4368,8 @@ HgfsRemoveLruNode(HgfsSessionInfo *session)   // IN: session info
    }
    handle = HgfsFileNode2Handle(lruNode);
    if (!HgfsRemoveFromCacheInternal(handle, session)) {
-      LOG(4, ("HgfsRemoveLruNode: Could not remove the node from cache.\n"));
+      LOG(4, ("%s: Could not remove the node from cache.\n", __FUNCTION__));
+
       return FALSE;
    }
 
@@ -4318,9 +4399,11 @@ HgfsAddToCache(HgfsHandle handle,        // IN: HGFS file handle
                HgfsSessionInfo *session) // IN: Session info
 {
    Bool added = FALSE;
+
    SyncMutex_Lock(&session->nodeArrayLock);
    added = HgfsAddToCacheInternal(handle, session);
    SyncMutex_Unlock(&session->nodeArrayLock);
+
    return added;
 }
 
@@ -4365,9 +4448,11 @@ HgfsCreateAndCacheFileNode(HgfsFileOpenInfo *openInfo, // IN: Open info struct
    /*
     * Get first component.
     */
+
    len = CPName_GetComponent(openInfo->cpName, inEnd, &next);
    if (len < 0) {
-      LOG(4, ("HgfsServerGetAccess: get first component failed\n"));
+      LOG(4, ("%s: get first component failed\n", __FUNCTION__));
+
       return FALSE;
    }
 
@@ -4381,24 +4466,21 @@ HgfsCreateAndCacheFileNode(HgfsFileOpenInfo *openInfo, // IN: Open info struct
    }
 
    SyncMutex_Lock(&session->nodeArrayLock);
-   node = HgfsAddNewFileNode(openInfo,
-                             localId,
-                             fileDesc,
-                             append,
-                             len,
-                             openInfo->cpName,
-                             sharedFolderOpen,
-                             session);
+   node = HgfsAddNewFileNode(openInfo, localId, fileDesc, append, len,
+                             openInfo->cpName, sharedFolderOpen, session);
+
    if (node == NULL) {
-      LOG(4, ("HgfsCreateAndCacheFileNode: Failed to add new node.\n"));
+      LOG(4, ("%s: Failed to add new node.\n", __FUNCTION__));
       SyncMutex_Unlock(&session->nodeArrayLock);
+
       return FALSE;
    }
    handle = HgfsFileNode2Handle(node);
 
    if (!HgfsAddToCacheInternal(handle, session)) {
-      LOG(4, ("HgfsCreateAndCacheFileNode: Failed to add node to the cache.\n"));
+      LOG(4, ("%s: Failed to add node to the cache.\n", __FUNCTION__));
       SyncMutex_Unlock(&session->nodeArrayLock);
+
       return FALSE;
    }
    SyncMutex_Unlock(&session->nodeArrayLock);
@@ -4448,7 +4530,7 @@ HgfsUnpackOpenRequest(char const *packetIn,        // IN: request packet
       {
          HgfsRequestOpenV3 *requestV3 =
                           (HgfsRequestOpenV3 *)HGFS_REQ_GET_PAYLOAD_V3(packetIn);
-         LOG(4, ("HgfsUnpackOpenRequest: HGFS_OP_OPEN_V3\n"));
+         LOG(4, ("%s: HGFS_OP_OPEN_V3\n", __FUNCTION__));
 
 
          /* Enforced by the dispatch function. */
@@ -4464,8 +4546,10 @@ HgfsUnpackOpenRequest(char const *packetIn,        // IN: request packet
           * requestV3->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV3->fileName.length > extra) {
             /* The input packet is smaller than the request. */
+
             return FALSE;
          }
 
@@ -4474,6 +4558,7 @@ HgfsUnpackOpenRequest(char const *packetIn,        // IN: request packet
           * garbage, but it's simpler to copy everything now and check the
           * valid bits before reading later.
           */
+
          openInfo->mask = requestV3->mask;
          openInfo->mode = requestV3->mode;
          openInfo->cpName = requestV3->fileName.name;
@@ -4502,6 +4587,7 @@ HgfsUnpackOpenRequest(char const *packetIn,        // IN: request packet
 
          if (!(requestV2->mask & HGFS_OPEN_VALID_FILE_NAME)) {
             /* We do not support open requests without a valid file name. */
+
             return FALSE;
          }
 
@@ -4509,6 +4595,7 @@ HgfsUnpackOpenRequest(char const *packetIn,        // IN: request packet
           * requestV2->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV2->fileName.length > extra) {
             /* The input packet is smaller than the request. */
             return FALSE;
@@ -4519,6 +4606,7 @@ HgfsUnpackOpenRequest(char const *packetIn,        // IN: request packet
           * garbage, but it's simpler to copy everything now and check the
           * valid bits before reading later.
           */
+
          openInfo->mask = requestV2->mask;
          openInfo->mode = requestV2->mode;
          openInfo->cpName = requestV2->fileName.name;
@@ -4537,8 +4625,7 @@ HgfsUnpackOpenRequest(char const *packetIn,        // IN: request packet
       }
    case HGFS_OP_OPEN:
       {
-         HgfsRequestOpen *requestV1 =
-            (HgfsRequestOpen *)packetIn;
+         HgfsRequestOpen *requestV1 = (HgfsRequestOpen *)packetIn;
 
          /* Enforced by the dispatch function. */
          ASSERT(packetSize >= sizeof *requestV1);
@@ -4551,14 +4638,15 @@ HgfsUnpackOpenRequest(char const *packetIn,        // IN: request packet
 
          if (requestV1->fileName.length > extra) {
             /* The input packet is smaller than the request. */
+
             return FALSE;
          }
 
          /* For OpenV1 requests, we know exactly what fields we expect. */
          openInfo->mask = HGFS_OPEN_VALID_MODE |
-            HGFS_OPEN_VALID_FLAGS |
-            HGFS_OPEN_VALID_OWNER_PERMS |
-            HGFS_OPEN_VALID_FILE_NAME;
+                          HGFS_OPEN_VALID_FLAGS |
+                          HGFS_OPEN_VALID_OWNER_PERMS |
+                          HGFS_OPEN_VALID_FILE_NAME;
          openInfo->mode = requestV1->mode;
          openInfo->cpName = requestV1->fileName.name;
          openInfo->cpNameSize = requestV1->fileName.length;
@@ -4713,8 +4801,8 @@ HgfsUnpackDeleteRequest(char const *packetIn,        // IN: request packet
    case HGFS_OP_DELETE_DIR_V3: {
       HgfsRequestDeleteV3 *requestV3;
 
-      requestV3 = (HgfsRequestDeleteV3 *)HGFS_REQ_GET_PAYLOAD_V3(packetIn);
-      LOG(4, ("HgfsUnpackDeleteRequest: HGFS_OP_DELETE_DIR_V3\n"));
+      requestV3 = (HgfsRequestDeleteV3 *) HGFS_REQ_GET_PAYLOAD_V3(packetIn);
+      LOG(4, ("%s: HGFS_OP_DELETE_DIR_V3\n", __FUNCTION__));
 
       /* Enforced by the dispatch function. */
       ASSERT(packetSize >= HGFS_REQ_PAYLOAD_SIZE_V3(requestV3));
@@ -4726,6 +4814,7 @@ HgfsUnpackDeleteRequest(char const *packetIn,        // IN: request packet
        * If we've been asked to reuse a handle, we don't need to look at, let
        * alone test the filename or its length.
        */
+
       if (requestV3->fileName.flags & HGFS_FILE_NAME_USE_FILE_DESC) {
          *file = requestV3->fileName.fid;
          *cpName = NULL;
@@ -4738,8 +4827,10 @@ HgfsUnpackDeleteRequest(char const *packetIn,        // IN: request packet
           * request->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV3->fileName.length > extra) {
             /* The input packet is smaller than the request */
+
             return FALSE;
          }
          *cpName = requestV3->fileName.name;
@@ -4763,6 +4854,7 @@ HgfsUnpackDeleteRequest(char const *packetIn,        // IN: request packet
        * If we've been asked to reuse a handle, we don't need to look at, let
        * alone test the filename or its length.
        */
+
       if (*hints & HGFS_DELETE_HINT_USE_FILE_DESC) {
          *file = requestV2->file;
          *cpName = NULL;
@@ -4774,8 +4866,10 @@ HgfsUnpackDeleteRequest(char const *packetIn,        // IN: request packet
           * request->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV2->fileName.length > extra) {
             /* The input packet is smaller than the request */
+
             return FALSE;
          }
          *cpName = requestV2->fileName.name;
@@ -4794,12 +4888,13 @@ HgfsUnpackDeleteRequest(char const *packetIn,        // IN: request packet
       extra = packetSize - sizeof *requestV1;
 
       /*
-       * request->fileName.length is user-provided, so this test must be carefully
-       * written to prevent wraparounds.
+       * request->fileName.length is user-provided, so this test must be
+       * carefully written to prevent wraparounds.
        */
 
       if (requestV1->fileName.length > extra) {
          /* The input packet is smaller than the request. */
+
          return FALSE;
       }
       *cpName = requestV1->fileName.name;
@@ -4873,7 +4968,7 @@ HgfsPackDeleteReply(char const *packetIn,      // IN: incoming packet
       ((HgfsReply *)*packetOut)->status = HgfsConvertFromInternalStatus(status);
       break;
    default:
-      LOG(4, ("HgfsPackDeleteReply: invalid op code %d\n", header->op));
+      LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, header->op));
       result = FALSE;
       break;
    }
@@ -4951,7 +5046,7 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
       HgfsFileNameV3 *newName;
 
       requestV3 = (HgfsRequestRenameV3 *)HGFS_REQ_GET_PAYLOAD_V3(packetIn);
-      LOG(4, ("HgfsUnpackRenameRequest: HGFS_OP_RENAME_V3\n"));
+      LOG(4, ("%s: HGFS_OP_RENAME_V3\n", __FUNCTION__));
 
       /* Enforced by the dispatch function. */
       ASSERT(packetSize >= HGFS_REQ_PAYLOAD_SIZE_V3(requestV3));
@@ -4964,6 +5059,7 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
        * alone test the filename or its length. This applies to the source
        * and the target.
        */
+
       if (requestV3->oldName.flags & HGFS_FILE_NAME_USE_FILE_DESC) {
          *srcFile = requestV3->oldName.fid;
          *cpOldName = NULL;
@@ -4977,8 +5073,10 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
           * request->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV3->oldName.length > extra) {
             /* The input packet is smaller than the request */
+
             return FALSE;
          }
 
@@ -4986,7 +5084,8 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
          *cpOldName = requestV3->oldName.name;
          *cpOldNameLen = requestV3->oldName.length;
          *oldCaseFlags = requestV3->oldName.caseType;
-         newName = (HgfsFileNameV3 *)(requestV3->oldName.name + 1 + *cpOldNameLen);
+         newName = (HgfsFileNameV3 *)(requestV3->oldName.name + 1 +
+                                                             *cpOldNameLen);
       }
       extra -= *cpOldNameLen;
 
@@ -4999,6 +5098,7 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
       } else {
          if (newName->length > extra) {
             /* The input packet is smaller than the request */
+
             return FALSE;
          }
 
@@ -5027,6 +5127,7 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
        * alone test the filename or its length. This applies to the source
        * and the target.
        */
+
       if (*hints & HGFS_RENAME_HINT_USE_SRCFILE_DESC) {
          *srcFile = requestV2->srcFile;
          *cpOldName = NULL;
@@ -5037,8 +5138,10 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
           * request->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV2->oldName.length > extra) {
             /* The input packet is smaller than the request */
+
             return FALSE;
          }
 
@@ -5058,6 +5161,7 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
                                        + *cpOldNameLen);
          if (newName->length > extra) {
             /* The input packet is smaller than the request */
+
             return FALSE;
          }
 
@@ -5080,11 +5184,13 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
       extra = packetSize - sizeof *requestV1;
 
       /*
-       * request->fileName.length is user-provided, so this test must be carefully
-       * written to prevent wraparounds.
+       * request->fileName.length is user-provided, so this test must be
+       * carefully written to prevent wraparounds.
        */
+
       if (requestV1->oldName.length > extra) {
          /* The input packet is smaller than the request. */
+
          return FALSE;
       }
 
@@ -5099,8 +5205,10 @@ HgfsUnpackRenameRequest(char const *packetIn,       // IN: request packet
        * newName->length is user-provided, so this test must be carefully
        * written to prevent wraparounds.
        */
+
       if (newName->length > extra) {
          /* The input packet is smaller than the request. */
+
          return FALSE;
       }
 
@@ -5169,13 +5277,13 @@ HgfsPackRenameReply(char const *packetIn,      // IN: incoming packet
    }
    case HGFS_OP_RENAME_V2:
    case HGFS_OP_RENAME:
-      *packetSize = sizeof(HgfsReplyRename);
+      *packetSize = sizeof (HgfsReplyRename);
       *packetOut = Util_SafeMalloc(*packetSize);
       ((HgfsReply *)*packetOut)->id = header->id;
       ((HgfsReply *)*packetOut)->status = HgfsConvertFromInternalStatus(status);
       break;
    default:
-      LOG(4, ("HgfsPackRenameReply: invalid op code %d\n", header->op));
+      LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, header->op));
       result = FALSE;
       break;
    }
@@ -5247,6 +5355,7 @@ HgfsUnpackGetattrRequest(char const *packetIn,       // IN: request packet
        * If we've been asked to reuse a handle, we don't need to look at, let
        * alone test the filename or its length.
        */
+
       *hints = requestV3->hints;
       if (requestV3->fileName.flags & HGFS_FILE_NAME_USE_FILE_DESC) {
          *file = requestV3->fileName.fid;
@@ -5260,15 +5369,17 @@ HgfsUnpackGetattrRequest(char const *packetIn,       // IN: request packet
           * request->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV3->fileName.length > extra) {
             /* The input packet is smaller than the request */
+
             return FALSE;
          }
          *cpName = requestV3->fileName.name;
          *cpNameSize = requestV3->fileName.length;
          *caseType = requestV3->fileName.caseType;
       }
-      LOG(4, ("HgfsUnpackGetattrRequest: HGFS_OP_GETATTR_V3: %u\n", *caseType));
+      LOG(4, ("%s: HGFS_OP_GETATTR_V3: %u\n", __FUNCTION__, *caseType));
       break;
    }
 
@@ -5283,6 +5394,7 @@ HgfsUnpackGetattrRequest(char const *packetIn,       // IN: request packet
        * If we've been asked to reuse a handle, we don't need to look at, let
        * alone test the filename or its length.
        */
+
       *hints = requestV2->hints;
       if (*hints & HGFS_ATTR_HINT_USE_FILE_DESC) {
          *file = requestV2->file;
@@ -5295,8 +5407,10 @@ HgfsUnpackGetattrRequest(char const *packetIn,       // IN: request packet
           * request->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV2->fileName.length > extra) {
             /* The input packet is smaller than the request */
+
             return FALSE;
          }
          *cpName = requestV2->fileName.name;
@@ -5314,12 +5428,13 @@ HgfsUnpackGetattrRequest(char const *packetIn,       // IN: request packet
       extra = packetSize - sizeof *requestV1;
 
       /*
-       * request->fileName.length is user-provided, so this test must be carefully
-       * written to prevent wraparounds.
+       * request->fileName.length is user-provided, so this test must be
+       * carefully written to prevent wraparounds.
        */
 
       if (requestV1->fileName.length > extra) {
          /* The input packet is smaller than the request. */
+
          return FALSE;
       }
       *cpName = requestV1->fileName.name;
@@ -5349,6 +5464,7 @@ HgfsUnpackGetattrRequest(char const *packetIn,       // IN: request packet
    attrInfo->userId = 0;
    attrInfo->groupId = 0;
    attrInfo->hostFileId = 0;
+
    return TRUE;
 }
 
@@ -5401,7 +5517,7 @@ HgfsPackGetattrReply(char const *packetIn,       // IN: incoming packet
       reply = (HgfsReplyGetattrV3 *)HGFS_REP_GET_PAYLOAD_V3(*packetOut);
       reply->attr.mask = attr->mask;
       reply->attr.type = attr->type;
-      LOG(4, ("HgfsPackGetattrReply: attr type: %u\n", reply->attr.type));
+      LOG(4, ("%s: attr type: %u\n", __FUNCTION__, reply->attr.type));
 
       /*
        * Is there enough space in the request packet for the utf8 name?
@@ -5412,9 +5528,11 @@ HgfsPackGetattrReply(char const *packetIn,       // IN: incoming packet
        * Also keep in mind that sizeof *reply already contains one character,
        * which we'll consider the nul terminator.
        */
+
       if (utf8TargetNameLen > HGFS_PACKET_MAX - HGFS_REP_PAYLOAD_SIZE_V3(reply)) {
          return FALSE;
       }
+
       if (utf8TargetName) {
          memcpy(reply->symlinkTarget.name, utf8TargetName, utf8TargetNameLen);
          CPNameLite_ConvertTo(reply->symlinkTarget.name, utf8TargetNameLen,
@@ -5469,6 +5587,7 @@ HgfsPackGetattrReply(char const *packetIn,       // IN: incoming packet
        * Also keep in mind that sizeof *reply already contains one character,
        * which we'll consider the nul terminator.
        */
+
       if (utf8TargetNameLen > HGFS_PACKET_MAX - sizeof *reply) {
          return FALSE;
       }
@@ -5527,7 +5646,8 @@ HgfsPackGetattrReply(char const *packetIn,       // IN: incoming packet
    }
 
    default:
-      LOG(4, ("HgfsPackGetattrReply: Invalid GetAttr op.\n"));
+      LOG(4, ("%s: Invalid GetAttr op.\n", __FUNCTION__));
+
       return FALSE;
    }
 
@@ -5582,7 +5702,7 @@ HgfsUnpackSearchReadRequest(const char *packetIn,         // IN: request packet
       *hgfsSearchHandle = request->search;
       *offset = request->offset;
 
-      LOG(4, ("HgfsUnpackSearchReadRequest: HGFS_OP_SEARCH_READ_V3\n"));
+      LOG(4, ("%s: HGFS_OP_SEARCH_READ_V3\n", __FUNCTION__));
    } else {
       HgfsRequestSearchRead *request;
 
@@ -5657,7 +5777,8 @@ HgfsPackSearchReadReply(char const *packetIn,      // IN: incoming packet
       HgfsReplySearchReadV3 *reply;
       HgfsDirEntry *dirent;
 
-      *packetSize = HGFS_REP_PAYLOAD_SIZE_V3(reply) + utf8NameLen + sizeof *dirent;
+      *packetSize = HGFS_REP_PAYLOAD_SIZE_V3(reply) + utf8NameLen +
+                                                               sizeof *dirent;
       *packetOut = Util_SafeMalloc(*packetSize);
 
       replyHeader = (HgfsReply *)(*packetOut);
@@ -5676,8 +5797,9 @@ HgfsPackSearchReadReply(char const *packetIn,      // IN: incoming packet
        * Also keep in mind that sizeof *reply already contains one character,
        * which we'll consider the nul terminator.
        */
+
       if (utf8NameLen > HGFS_PACKET_MAX - HGFS_REP_PAYLOAD_SIZE_V3(reply) -
-                                          sizeof(struct HgfsDirEntry)) {
+                                          sizeof *dirent) {
          return FALSE;
       }
 
@@ -5691,6 +5813,7 @@ HgfsPackSearchReadReply(char const *packetIn,      // IN: incoming packet
 
       if (utf8NameLen == 0) {
          /* No entry. */
+
          return TRUE;
       }
 
@@ -5735,6 +5858,7 @@ HgfsPackSearchReadReply(char const *packetIn,      // IN: incoming packet
        * Also keep in mind that sizeof *reply already contains one character,
        * which we'll consider the nul terminator.
        */
+
       if (utf8NameLen > HGFS_PACKET_MAX - sizeof *reply) {
          return FALSE;
       }
@@ -5743,6 +5867,7 @@ HgfsPackSearchReadReply(char const *packetIn,      // IN: incoming packet
 
       if (utf8NameLen == 0) {
          /* No entry. */
+
          return TRUE;
       }
 
@@ -5787,6 +5912,7 @@ HgfsPackSearchReadReply(char const *packetIn,      // IN: incoming packet
        * Also keep in mind that sizeof *reply already contains one character,
        * which we'll consider the nul terminator.
        */
+
       if (utf8NameLen > HGFS_PACKET_MAX - sizeof *reply) {
          return FALSE;
       }
@@ -5795,6 +5921,7 @@ HgfsPackSearchReadReply(char const *packetIn,      // IN: incoming packet
 
       if (utf8NameLen == 0) {
          /* No entry. */
+
          return TRUE;
       }
       memcpy(reply->fileName.name, utf8Name, utf8NameLen);
@@ -5816,7 +5943,8 @@ HgfsPackSearchReadReply(char const *packetIn,      // IN: incoming packet
    }
 
    default: {
-      LOG(4, ("HgfsPackSearchReadReply: Invalid SearchRead Op."));
+      LOG(4, ("%s: Invalid SearchRead Op.", __FUNCTION__));
+
       return FALSE;
    }
    }
@@ -5901,6 +6029,7 @@ HgfsUnpackSetattrRequest(char const *packetIn,       // IN: request packet
           * If we've been asked to reuse a handle, we don't need to look at,
           * let alone test the filename or its length.
           */
+
          if (requestV3->fileName.flags & HGFS_FILE_NAME_USE_FILE_DESC) {
             *file = requestV3->fileName.fid;
             *cpName = NULL;
@@ -5912,6 +6041,7 @@ HgfsUnpackSetattrRequest(char const *packetIn,       // IN: request packet
 
             if (requestV3->fileName.length > extra) {
                /* The input packet is smaller than the request. */
+
                return FALSE;
             }
             /* It is now safe to read the file name. */
@@ -5919,7 +6049,8 @@ HgfsUnpackSetattrRequest(char const *packetIn,       // IN: request packet
             *cpNameSize = requestV3->fileName.length;
             *caseType = requestV3->fileName.caseType;
          }
-         LOG(4, ("HgfsUnpackSetattrRequest: unpacking HGFS_OP_SETATTR_V3, %u\n", *caseType));
+         LOG(4, ("%s: unpacking HGFS_OP_SETATTR_V3, %u\n", __FUNCTION__,
+                 *caseType));
          break;
       }
 
@@ -5954,6 +6085,7 @@ HgfsUnpackSetattrRequest(char const *packetIn,       // IN: request packet
           * If we've been asked to reuse a handle, we don't need to look at,
           * let alone test the filename or its length.
           */
+
          if (*hints & HGFS_ATTR_HINT_USE_FILE_DESC) {
             *file = requestV2->file;
             *cpName = NULL;
@@ -5963,13 +6095,14 @@ HgfsUnpackSetattrRequest(char const *packetIn,       // IN: request packet
 
             if (requestV2->fileName.length > extra) {
                /* The input packet is smaller than the request. */
+
                return FALSE;
             }
             /* It is now safe to read the file name. */
             *cpName = requestV2->fileName.name;
             *cpNameSize = requestV2->fileName.length;
          }
-         LOG(4, ("HgfsUnpackSetattrRequest: unpacking HGFS_OP_SETATTR_V2\n"));
+         LOG(4, ("%s: unpacking HGFS_OP_SETATTR_V2\n", __FUNCTION__));
          break;
       }
    case HGFS_OP_SETATTR:
@@ -5988,6 +6121,7 @@ HgfsUnpackSetattrRequest(char const *packetIn,       // IN: request packet
 
          if (requestV1->fileName.length > extra) {
             /* The input packet is smaller than the request. */
+
             return FALSE;
          }
 
@@ -5996,40 +6130,29 @@ HgfsUnpackSetattrRequest(char const *packetIn,       // IN: request packet
          *cpNameSize = requestV1->fileName.length;
 
          attr->mask = 0;
-         attr->mask |=
-            requestV1->update & HGFS_ATTR_SIZE ?
-            HGFS_ATTR_VALID_SIZE :
-            0;
-         attr->mask |=
-            requestV1->update & HGFS_ATTR_CREATE_TIME ?
-            HGFS_ATTR_VALID_CREATE_TIME :
-            0;
-         attr->mask |=
-            requestV1->update & HGFS_ATTR_ACCESS_TIME ?
-            HGFS_ATTR_VALID_ACCESS_TIME :
-            0;
-         attr->mask |=
-            requestV1->update & HGFS_ATTR_WRITE_TIME ?
-            HGFS_ATTR_VALID_WRITE_TIME :
-            0;
-         attr->mask |=
-            requestV1->update & HGFS_ATTR_CHANGE_TIME ?
-            HGFS_ATTR_VALID_CHANGE_TIME :
-            0;
-         attr->mask |=
-            requestV1->update & HGFS_ATTR_PERMISSIONS ?
-            HGFS_ATTR_VALID_OWNER_PERMS :
-            0;
-
-         *hints     |=
-            requestV1->update & HGFS_ATTR_ACCESS_TIME_SET ?
-            HGFS_ATTR_HINT_SET_ACCESS_TIME :
-            0;
-
-         *hints     |=
-            requestV1->update & HGFS_ATTR_WRITE_TIME_SET ?
-            HGFS_ATTR_HINT_SET_WRITE_TIME :
-            0;
+         attr->mask |= requestV1->update & HGFS_ATTR_SIZE ?
+                                                  HGFS_ATTR_VALID_SIZE : 0;
+         attr->mask |= requestV1->update & HGFS_ATTR_CREATE_TIME ?
+                                                  HGFS_ATTR_VALID_CREATE_TIME :
+                                                  0;
+         attr->mask |= requestV1->update & HGFS_ATTR_ACCESS_TIME ?
+                                                  HGFS_ATTR_VALID_ACCESS_TIME :
+                                                  0;
+         attr->mask |= requestV1->update & HGFS_ATTR_WRITE_TIME ?
+                                                  HGFS_ATTR_VALID_WRITE_TIME :
+                                                  0;
+         attr->mask |= requestV1->update & HGFS_ATTR_CHANGE_TIME ?
+                                                  HGFS_ATTR_VALID_CHANGE_TIME :
+                                                  0;
+         attr->mask |= requestV1->update & HGFS_ATTR_PERMISSIONS ?
+                                                  HGFS_ATTR_VALID_OWNER_PERMS :
+                                                  0;
+         *hints     |= requestV1->update & HGFS_ATTR_ACCESS_TIME_SET ?
+                                                 HGFS_ATTR_HINT_SET_ACCESS_TIME :
+                                                 0;
+         *hints     |= requestV1->update & HGFS_ATTR_WRITE_TIME_SET ?
+                                               HGFS_ATTR_HINT_SET_WRITE_TIME :
+                                               0;
 
          attr->type = requestV1->attr.type;
          attr->size = requestV1->attr.size;
@@ -6038,7 +6161,7 @@ HgfsUnpackSetattrRequest(char const *packetIn,       // IN: request packet
          attr->writeTime = requestV1->attr.writeTime;
          attr->attrChangeTime = requestV1->attr.attrChangeTime;
          attr->ownerPerms = requestV1->attr.permissions;
-         LOG(4, ("HgfsUnpackSetattrRequest: unpacking HGFS_OP_SETATTR\n"));
+         LOG(4, ("%s: unpacking HGFS_OP_SETATTR\n", __FUNCTION__));
          break;
       }
    default:
@@ -6113,11 +6236,12 @@ HgfsPackSetattrReply(char const *packetIn,      // IN: incoming packet
    }
    default:
       result = FALSE;
-      LOG(4, ("HgfsPackSetattrReply: invalid op code %d\n", header->op));
+      LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, header->op));
       break;
    }
 
    ASSERT(result);
+
    return result;
 }
 
@@ -6168,6 +6292,7 @@ HgfsUnpackCreateDirRequest(char const *packetIn,    // IN: incoming packet
 
          if (!(requestV3->mask & HGFS_CREATE_DIR_VALID_FILE_NAME)) {
             /* We do not support requests without a valid file name. */
+
             return FALSE;
          }
 
@@ -6175,8 +6300,10 @@ HgfsUnpackCreateDirRequest(char const *packetIn,    // IN: incoming packet
           * requestV3->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV3->fileName.length > extra) {
             /* The input packet is smaller than the request. */
+
             return FALSE;
          }
 
@@ -6185,6 +6312,7 @@ HgfsUnpackCreateDirRequest(char const *packetIn,    // IN: incoming packet
           * garbage, but it's simpler to copy everything now and check the
           * valid bits before reading later.
           */
+
          info->mask = requestV3->mask;
          info->cpName = requestV3->fileName.name;
          info->cpNameSize = requestV3->fileName.length;
@@ -6194,7 +6322,7 @@ HgfsUnpackCreateDirRequest(char const *packetIn,    // IN: incoming packet
          info->ownerPerms = requestV3->ownerPerms;
          info->groupPerms = requestV3->groupPerms;
          info->otherPerms = requestV3->otherPerms;
-         LOG(4, ("HgfsUnpackCreateDirRequest: HGFS_OP_CREATE_DIR_V3\n"));
+         LOG(4, ("%s: HGFS_OP_CREATE_DIR_V3\n", __FUNCTION__));
          break;
       }
    case HGFS_OP_CREATE_DIR_V2:
@@ -6208,6 +6336,7 @@ HgfsUnpackCreateDirRequest(char const *packetIn,    // IN: incoming packet
 
          if (!(requestV2->mask & HGFS_CREATE_DIR_VALID_FILE_NAME)) {
             /* We do not support requests without a valid file name. */
+
             return FALSE;
          }
 
@@ -6215,8 +6344,10 @@ HgfsUnpackCreateDirRequest(char const *packetIn,    // IN: incoming packet
           * requestV2->fileName.length is user-provided, so this test must be
           * carefully written to prevent wraparounds.
           */
+
          if (requestV2->fileName.length > extra) {
             /* The input packet is smaller than the request. */
+
             return FALSE;
          }
 
@@ -6225,6 +6356,7 @@ HgfsUnpackCreateDirRequest(char const *packetIn,    // IN: incoming packet
           * garbage, but it's simpler to copy everything now and check the
           * valid bits before reading later.
           */
+
          info->mask = requestV2->mask;
          info->cpName = requestV2->fileName.name;
          info->cpNameSize = requestV2->fileName.length;
@@ -6251,13 +6383,13 @@ HgfsUnpackCreateDirRequest(char const *packetIn,    // IN: incoming packet
 
          if (requestV1->fileName.length > extra) {
             /* The input packet is smaller than the request. */
+
             return FALSE;
          }
 
          /* For CreateDirV1 requests, we know exactly what fields we expect. */
-         info->mask =
-            HGFS_CREATE_DIR_VALID_OWNER_PERMS |
-            HGFS_CREATE_DIR_VALID_FILE_NAME;
+         info->mask = HGFS_CREATE_DIR_VALID_OWNER_PERMS |
+                      HGFS_CREATE_DIR_VALID_FILE_NAME;
          info->cpName = requestV1->fileName.name;
          info->cpNameSize = requestV1->fileName.length;
          info->ownerPerms = requestV1->permissions;
@@ -6321,13 +6453,13 @@ HgfsPackCreateDirReply(char const *packetIn,      // IN: create dir operation ve
    }
    case HGFS_OP_CREATE_DIR_V2:
    case HGFS_OP_CREATE_DIR:
-      *packetSize = sizeof(HgfsReplyCreateDir);
+      *packetSize = sizeof (HgfsReplyCreateDir);
       *packetOut = Util_SafeMalloc(*packetSize);
       ((HgfsReply *)*packetOut)->id = header->id;
       ((HgfsReply *)*packetOut)->status = HgfsConvertFromInternalStatus(status);
       break;
    default:
-      LOG(4, ("HgfsPackCreateDirReply: invalid op code %d\n", header->op));
+      LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, header->op));
       result = FALSE;
       break;
    }
@@ -6343,9 +6475,9 @@ HgfsPackCreateDirReply(char const *packetIn,      // IN: create dir operation ve
  *
  * HgfsBuildRelativePath --
  *
- *    Generates relative file path which need to be used a symbolic link target which
- *    would generate target name defined in "target" if the path to symbolic link
- *    file defined in the "source".
+ *    Generates relative file path which need to be used a symbolic link
+ *    target which would generate target name defined in "target" if the path
+ *    to symbolic link file defined in the "source".
  *    Both source and target parameters represent absolute paths.
  *
  * Results:
@@ -6370,7 +6502,12 @@ HgfsBuildRelativePath(const char* source,    // IN: source file name
    size_t targetSize;
    char *result;
    char *currentPosition;
-    /*  First remove the part of the path which is common between source and target */
+
+   /*
+    * First remove the part of the path which is common between source and
+    * target
+    */
+
    while (*relativeSource != '\0' && *relativeTarget != '\0') {
       sourceSep = strchr(relativeSource, DIRSEPC);
       targetSep = strchr(relativeTarget, DIRSEPC);
@@ -6380,16 +6517,19 @@ HgfsBuildRelativePath(const char* source,    // IN: source file name
       if ((sourceSep - relativeSource) != (targetSep - relativeTarget)) {
          break;
       }
-      if (strncmp(relativeSource, relativeTarget, (targetSep - relativeTarget)) != 0) {
+      if (strncmp(relativeSource, relativeTarget,
+                  (targetSep - relativeTarget)) != 0) {
          break;
       }
       relativeSource = sourceSep + 1;
       relativeTarget = targetSep + 1;
    };
+
    /*
-    *  Find out how many directories deep the source file is from the common part of the
-    *  path.
+    * Find out how many directories deep the source file is from the common
+    * part of the  path.
     */
+
    while(*relativeSource != '\0') {
       sourceSep = strchr(relativeSource, DIRSEPC);
       if (sourceSep != NULL) {
@@ -6412,7 +6552,9 @@ HgfsBuildRelativePath(const char* source,    // IN: source file name
     * Consruct relative path by adding level number of "../"
     * to the relative target path.
     */
-   targetSize = level * HGFS_PARENT_DIR_LEN + strlen(relativeTarget) + sizeof '\0';
+
+   targetSize = level * HGFS_PARENT_DIR_LEN + strlen(relativeTarget) +
+                                                                  sizeof '\0';
    result = malloc(targetSize);
    currentPosition = result;
    if (result != NULL) {
@@ -6421,8 +6563,10 @@ HgfsBuildRelativePath(const char* source,    // IN: source file name
          level--;
          currentPosition += HGFS_PARENT_DIR_LEN;
       }
-      memcpy(currentPosition, relativeTarget, strlen(relativeTarget) + sizeof '\0');
+      memcpy(currentPosition, relativeTarget, strlen(relativeTarget) +
+                                                                 sizeof '\0');
    }
+
    return result;
 }
 
@@ -6437,8 +6581,8 @@ HgfsBuildRelativePath(const char* source,    // IN: source file name
  *
  *    XXX:
  *    The function must build directory notification packet and send it to the
- *    client. At the moment it just logs a message, actual logic will be implemented
- *    later when required infrastructure is ready.
+ *    client. At the moment it just logs a message, actual logic will be
+ *    implemented later when required infrastructure is ready.
  *
  * Results:
  *    None.
@@ -6456,12 +6600,9 @@ Hgfs_NotificationCallback(SharedFolderHandle sharedFolder,
                           char* newName,
                           uint32 mask)
 {
-    LOG(4, ("Hgfs_NotificationCallback: notification for folder: %d index: %d"
-            " file name %s (new name %s) mask %x\n",
-            sharedFolder,
-            (int)subscriber,
-            name,
-            (newName == NULL) ? "" : newName,
+    LOG(4, ("%s: notification for folder: %d index: %d file name %s "
+            "(new name %s) mask %x\n", __FUNCTION__, sharedFolder,
+            (int)subscriber, name, (newName == NULL) ? "" : newName,
             mask));
 }
 
@@ -6510,6 +6651,7 @@ HgfsServerOplockBreakReply(const unsigned char *packetIn, // IN: Reply packet
     * is double checked in HgfsAckOplockBreak, so we'd be safe from a garbage
     * value.
     */
+
    HgfsAckOplockBreak(lockData, reply->serverLock);
 }
 
@@ -6546,7 +6688,7 @@ HgfsServerOplockBreak(ServerLockData *lockData)
    HgfsRequestServerLockChange *request;
    HgfsServerLock lock;
 
-   LOG(4, ("HgfsServerOplockBreak: entered\n"));
+   LOG(4, ("%s: entered\n", __FUNCTION__));
 
    /*
     * XXX: Just because the file in not in the cache on the server,
@@ -6560,18 +6702,19 @@ HgfsServerOplockBreak(ServerLockData *lockData)
     * cache, or it had no lock, chances are someone else (maybe the VCPU
     * thread) broke the oplock and/or closed the file.
     */
+
    if (!HgfsFileDesc2Handle(lockData->fileDesc, &hgfsHandle)) {
-      LOG(4, ("HgfsServerOplockBreak: file is not in the cache\n"));
+      LOG(4, ("%s: file is not in the cache\n", __FUNCTION__));
       goto free_and_exit;
    }
 
    if (!HgfsHandle2ServerLock(hgfsHandle, &lock)) {
-      LOG(4, ("HgfsServerOplockBreak: could not retrieve node's lock info.\n"));
+      LOG(4, ("%s: could not retrieve node's lock info.\n", __FUNCTION__));
       goto free_and_exit;
    }
 
    if (lock == HGFS_LOCK_NONE) {
-      LOG(4, ("HgfsServerOplockBreak: the file does not have a server lock.\n"));
+      LOG(4, ("%s: the file does not have a server lock.\n", __FUNCTION__));
       goto free_and_exit;
    }
 
@@ -6582,9 +6725,10 @@ HgfsServerOplockBreak(ServerLockData *lockData)
     * XXX: This should probably go into a common allocation function that
     * other out-of-band requests can use.
     */
+
    requestBuffer = malloc(sizeof *request + HGFS_CLIENT_CMD_LEN);
    if (requestBuffer == NULL) {
-      LOG(4, ("HgfsServerOplockBreak: could not allocate memory.\n"));
+      LOG(4, ("%s: could not allocate memory.\n", __FUNCTION__));
       goto ack_and_exit;
    }
 
@@ -6603,17 +6747,18 @@ HgfsServerOplockBreak(ServerLockData *lockData)
     * If for some reason we fail, we'll acknowledge the oplock break
     * immediately.
     */
-   if (HgfsServerManager_SendRequest(requestBuffer,
-                                     sizeof *request,
-                                     HgfsServerOplockBreakReply,
-                                     lockData)) {
+
+   if (HgfsServerManager_SendRequest(requestBuffer, sizeof *request,
+                                     HgfsServerOplockBreakReply, lockData)) {
       return;
    }
    free(requestBuffer);
 
   ack_and_exit:
    HgfsAckOplockBreak(lockData, HGFS_LOCK_NONE);
+
    return;
+
   free_and_exit:
    free(lockData);
 }
@@ -6630,7 +6775,7 @@ TestNodeFreeList(void)
    HgfsFileNode *node;
    unsigned int i;
 
-   printf("TestNodeFreeList: begin >>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
+   printf("%s: begin >>>>>>>>>>>>>>>>>>>>>>>>>>>\n", __FUNCTION__);
 
    for (i = 0; i < sizeof array / sizeof array[0]; i++) {
       char tempName[20];
@@ -6654,7 +6799,7 @@ TestNodeFreeList(void)
    }
 
    HgfsDumpAllNodes();
-   printf("TestNodeFreeList: end <<<<<<<<<<<<<<<<<<<<<<<<<< \n");
+   printf("%s: end <<<<<<<<<<<<<<<<<<<<<<<<<< \n", __FUNCTION__);
 }
 
 
@@ -6665,7 +6810,7 @@ TestSearchFreeList(void)
    HgfsSearch *search;
    unsigned int i;
 
-   printf("TestSearchFreeList: begin >>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
+   printf("%s: begin >>>>>>>>>>>>>>>>>>>>>>>>>>>\n", __FUNCTION__);
 
    for (i = 0; i < sizeof array / sizeof array[0]; i++) {
       char tempName[20];
@@ -6686,6 +6831,6 @@ TestSearchFreeList(void)
    }
 
    HgfsDumpAllSearches();
-   printf("TestSearchFreeList: end <<<<<<<<<<<<<<<<<<<<<<<<<< \n");
+   printf("%s: end <<<<<<<<<<<<<<<<<<<<<<<<<< \n", __FUNCTION__);
 }
 #endif
index a36895a32d236f666026bacf7fc31d1f9dec4cfc..9f8ff106d847ef1b65ce099a07630d34a5ec27d9 100644 (file)
@@ -388,12 +388,13 @@ HgfsServerSigOplockBreak(int sigNum,       // IN: Signal number
    ASSERT(clientData == NULL);
 
    fd = info->si_fd;
-   LOG(4, ("HgfsServerSigOplockBreak: Received SIGIO for fd %d\n", fd));
+   LOG(4, ("%s: Received SIGIO for fd %d\n", __FUNCTION__, fd));
 
    /*
     * We've got all we need from the signal handler, let it continue handling
     * signals of this type.
     */
+
    Sig_Continue(sigNum);
 
    /*
@@ -401,6 +402,7 @@ HgfsServerSigOplockBreak(int sigNum,       // IN: Signal number
     * break is pending will return the new lease we should use. It'll be
     * F_RDLCK if we can downgrade, or F_UNLCK if we should break altogether.
     */
+
    newLease = fcntl(fd, F_GETLEASE);
    if (newLease == F_RDLCK) {
       newServerLock = HGFS_LOCK_SHARED;
@@ -408,12 +410,12 @@ HgfsServerSigOplockBreak(int sigNum,       // IN: Signal number
       newServerLock = HGFS_LOCK_NONE;
    } else if (newLease == -1) {
       int error = errno;
-      Log("HgfsServerSigOplockBreak: Could not get old lease for fd %d: %s\n",
+      Log("%s: Could not get old lease for fd %d: %s\n", __FUNCTION__,
           fd, strerror(error));
       goto error;
    } else {
-      Log("HgfsServerSigOplockBreak: Unexpected reply to get lease for fd %d: "
-          "%d\n", fd, newLease);
+      Log("%s: Unexpected reply to get lease for fd %d: %d\n",
+          __FUNCTION__, fd, newLease);
       goto error;
    }
 
@@ -424,6 +426,7 @@ HgfsServerSigOplockBreak(int sigNum,       // IN: Signal number
     * the acknowledgement, and firing the platform-specific acknowledgement
     * function (where we'll downgrade the lease).
     */
+
    lockData = malloc(sizeof *lockData);
    if (lockData) {
       lockData->fileDesc = fd;
@@ -437,8 +440,8 @@ HgfsServerSigOplockBreak(int sigNum,       // IN: Signal number
       HgfsServerOplockBreak(lockData);
       return;
    } else {
-      Log("HgfsServerSigOplockBreak: Could not allocate memory for lease "
-          "break on behalf of fd %d\n", fd);
+      Log("%s: Could not allocate memory for lease break on behalf of fd %d\n",
+          __FUNCTION__, fd);
    }
 
   error:
@@ -592,7 +595,8 @@ HgfsServerGetOpenFlags(HgfsOpenFlags flagsIn, // IN
    arraySize = ARRAYSIZE(HgfsServerOpenFlags);
 
    if (flagsIn < 0 || flagsIn >= arraySize) {
-      Log("HgfsServerGetOpenFlags: Invalid HgfsOpenFlags %d\n", flagsIn);
+      Log("%s: Invalid HgfsOpenFlags %d\n", __FUNCTION__, flagsIn);
+
       return FALSE;
    }
 
@@ -696,7 +700,8 @@ HgfsServerGetOpenMode(HgfsFileOpenInfo *openInfo, // IN:  Open info to examine
    }
 
    if (!HGFS_OPEN_MODE_IS_VALID_MODE(openInfo->mode)) {
-      Log("HgfsServerGetOpenMode: Invalid HgfsOpenMode %d\n", openInfo->mode);
+      Log("%s: Invalid HgfsOpenMode %d\n", __FUNCTION__, openInfo->mode);
+
       return FALSE;
    }
 
@@ -728,8 +733,10 @@ HgfsCloseFile(fileDesc fileDesc) // IN: File descriptor
 {
    if (close(fileDesc) != 0) {
       int error = errno;
-      LOG(4, ("HgfsCloseFile: Could not close fd %d: %s\n", fileDesc,
+
+      LOG(4, ("%s: Could not close fd %d: %s\n", __FUNCTION__, fileDesc, 
               strerror(error)));
+
       return error;
    }
 
@@ -771,14 +778,17 @@ HgfsCheckFileNode(char const *localName,      // IN
 
    if (Posix_Stat(localName, &nodeStat) < 0) {
       int error = errno;
-      LOG(4, ("HgfsCheckFileNode: couldn't stat local file \"%s\": %s\n",
+
+      LOG(4, ("%s: couldn't stat local file \"%s\": %s\n", __FUNCTION__,
               localName, strerror(error)));
+
       return error;
    }
 
-   if (   nodeStat.st_dev != localId->volumeId
-       || nodeStat.st_ino != localId->fileId) {
-      LOG(4, ("HgfsCheckFileNode: local Id mismatch\n"));
+   if (nodeStat.st_dev != localId->volumeId ||
+       nodeStat.st_ino != localId->fileId) {
+      LOG(4, ("%s: local Id mismatch\n", __FUNCTION__));
+
       return ENOENT;
    }
 
@@ -829,27 +839,28 @@ HgfsGetFd(HgfsHandle hgfsHandle,    // IN:  HGFS file handle
     * path. Unfortuntely, even the fast path may need to look at the node's
     * append flag.
     */
+
    node.utf8Name = NULL;
    if (!HgfsGetNodeCopy(hgfsHandle, session, TRUE, &node)) {
       /* XXX: Technically, this can also fail if we're out of memory. */
-      LOG(4, ("HgfsGetFd: Invalid hgfs handle.\n"));
+      LOG(4, ("%s: Invalid hgfs handle.\n", __FUNCTION__));
       status = EBADF;
       goto exit;
    }
 
    /* If the node is found in the cache */
    if (HgfsIsCached(hgfsHandle, session)) {
-
       /*
        * If the append flag is set check to see if the file was opened
        * in append mode. If not, close the file and reopen it in append
        * mode.
        */
+
       if (append && !(node.flags & HGFS_FILE_NODE_APPEND_FL)) {
          status = HgfsCloseFile(node.fileDesc);
          if (status != 0) {
-            LOG(4, ("HgfsGetFd: Couldn't close file \"%s\" for reopening\n",
-                    node.utf8Name));
+            LOG(4, ("%s: Couldn't close file \"%s\" for reopening\n",
+                    __FUNCTION__, node.utf8Name));
             goto exit;
          }
 
@@ -857,8 +868,10 @@ HgfsGetFd(HgfsHandle hgfsHandle,    // IN:  HGFS file handle
           * Update the node in the cache with the new value of the append
           * flag.
           */
+
          if (!HgfsUpdateNodeAppendFlag(hgfsHandle, session, TRUE)) {
-            LOG(4, ("HgfsGetFd: Could not update the node in the cache\n"));
+            LOG(4, ("%s: Could not update the node in the cache\n",
+                    __FUNCTION__));
             status = EBADF;
             goto exit;
          }
@@ -873,6 +886,7 @@ HgfsGetFd(HgfsHandle hgfsHandle,    // IN:  HGFS file handle
     * reopening. This means we need to open a file. But first, verify
     * that the file we intend to open isn't stale.
     */
+
    status = HgfsCheckFileNode(node.utf8Name, &node.localId);
    if (status != 0) {
       goto exit;
@@ -882,6 +896,7 @@ HgfsGetFd(HgfsHandle hgfsHandle,    // IN:  HGFS file handle
     * We're not interested in creating a new file. So let's just get the
     * flags for a simple open request. This really should always work.
     */
+
    HgfsServerGetOpenFlags(0, &openFlags);
 
    /*
@@ -890,12 +905,14 @@ HgfsGetFd(HgfsHandle hgfsHandle,    // IN:  HGFS file handle
     *
     * XXX: We should use O_LARGEFILE, see lib/file/fileIOPosix.c --hpreg
     */
+
    newFd = Posix_Open(node.utf8Name,
                node.mode | openFlags | (append ? O_APPEND : 0));
 
    if (newFd < 0) {
       int error = errno;
-      LOG(4, ("HgfsGetFd: Couldn't open file \"%s\": %s\n",
+
+      LOG(4, ("%s: Couldn't open file \"%s\": %s\n", __FUNCTION__,
               node.utf8Name, strerror(errno)));
       status = error;
       goto exit;
@@ -905,15 +922,17 @@ HgfsGetFd(HgfsHandle hgfsHandle,    // IN:  HGFS file handle
     * Update the original node with the new value of the file desc.
     * This call might fail if the node is not used anymore.
     */
+
    if (!HgfsUpdateNodeFileDesc(hgfsHandle, session, newFd)) {
-      LOG(4, ("HgfsGetFd: Could not update the node -- node is not used.\n"));
+      LOG(4, ("%s: Could not update the node -- node is not used.\n",
+              __FUNCTION__));
       status = EBADF;
       goto exit;
    }
 
    /* Add the node to the cache. */
    if (!HgfsAddToCache(hgfsHandle, session)) {
-      LOG(4, ("HgfsGetFd: Could not add node to the cache\n"));
+      LOG(4, ("%s: Could not add node to the cache\n", __FUNCTION__));
       status = EBADF;
       goto exit;
    }
@@ -923,6 +942,7 @@ HgfsGetFd(HgfsHandle hgfsHandle,    // IN:  HGFS file handle
       *fd = newFd;
    }
    free(node.utf8Name);
+
    return status;
 }
 
@@ -1034,7 +1054,7 @@ HgfsValidateOpen(HgfsFileOpenInfo *openInfo, // IN: Open info struct
              openPerms);
    if (fd < 0) {
       error = errno;
-      LOG(4, ("HgfsValidateOpen: couldn't open file \"%s\": %s\n",
+      LOG(4, ("%s: couldn't open file \"%s\": %s\n", __FUNCTION__,
               openInfo->utf8Name, strerror(error)));
       status = error;
       goto exit;
@@ -1048,7 +1068,7 @@ HgfsValidateOpen(HgfsFileOpenInfo *openInfo, // IN: Open info struct
    /* Stat file to get its volume and file info */
    if (fstat(fd, &fileStat) < 0) {
       error = errno;
-      LOG(4, ("HgfsValidateOpen: couldn't stat local file \"%s\": %s\n",
+      LOG(4, ("%s: couldn't stat local file \"%s\": %s\n", __FUNCTION__,
               openInfo->utf8Name, strerror(error)));
       close(fd);
       status = error;
@@ -1129,10 +1149,12 @@ HgfsAcquireServerLock(fileDesc fileDesc,            // IN: OS handle
     *
     * XXX: Do I need to do fcntl(fileDesc, F_SETOWN, getpid())?
     */
+
    if (fcntl(fileDesc, F_SETSIG, SIGIO)) {
       error = errno;
-      Log("HgfsAcquireServerLock: Could not set SIGIO as the desired lease "
-          "break signal for fd %d: %s\n", fileDesc, strerror(error));
+      Log("%s: Could not set SIGIO as the desired lease break signal for "
+          "fd %d: %s\n", __FUNCTION__, fileDesc, strerror(error));
+
       return FALSE;
    }
 
@@ -1140,43 +1162,48 @@ HgfsAcquireServerLock(fileDesc fileDesc,            // IN: OS handle
     * If the client just wanted the best lock possible, start off with a write
     * lease and move down to a read lease if that was unavailable.
     */
+
    if ((desiredLock == HGFS_LOCK_OPPORTUNISTIC) ||
        (desiredLock == HGFS_LOCK_EXCLUSIVE)) {
       leaseType = F_WRLCK;
    } else if (desiredLock  == HGFS_LOCK_SHARED) {
       leaseType = F_RDLCK;
    } else {
-      LOG(4, ("HgfsAcquireServerLock: Unknown server lock\n"));
+      LOG(4, ("%s: Unknown server lock\n", __FUNCTION__));
+
       return FALSE;
    }
    if (fcntl(fileDesc, F_SETLEASE, leaseType)) {
-
       /*
        * If our client was opportunistic and we failed to get his lease because
        * someone else is already writing or reading to the file, try again with
        * a read lease.
        */
+
       if (desiredLock == HGFS_LOCK_OPPORTUNISTIC &&
           (errno == EAGAIN || errno == EACCES)) {
          leaseType = F_RDLCK;
          if (fcntl(fileDesc, F_SETLEASE, leaseType)) {
             error = errno;
-            LOG(4, ("HgfsAcquireServerLock: Could not get any opportunistic "
-                    "lease for fd %d: %s\n", fileDesc, strerror(error)));
+            LOG(4, ("%s: Could not get any opportunistic lease for fd %d: %s\n",
+                    __FUNCTION__, fileDesc, strerror(error)));
+
             return FALSE;
          }
       } else {
          error = errno;
-         LOG(4, ("HgfsAcquireServerLock: Could not get %s lease for fd %d: "
-                 "%s\n", leaseType == F_WRLCK ? "write" : "read", fileDesc,
-                 strerror(errno)));
+         LOG(4, ("%s: Could not get %s lease for fd %d: %s\n",
+                 __FUNCTION__, leaseType == F_WRLCK ? "write" : "read",
+                 fileDesc, strerror(errno)));
+
          return FALSE;
       }
    }
 
    /* Got a lease of some kind. */
-   LOG(4, ("HgfsAcquireServerLock: Got %s lease for fd %d\n",
+   LOG(4, ("%s: Got %s lease for fd %d\n", __FUNCTION__,
            leaseType == F_WRLCK ? "write" : "read", fileDesc));
+
    *serverLock = leaseType == F_WRLCK ? HGFS_LOCK_EXCLUSIVE : HGFS_LOCK_SHARED;
    return TRUE;
 #else
@@ -1234,12 +1261,14 @@ HgfsGetattrResolveAlias(char const *fileName,       // IN:  Input filename
     * 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, ("HgfsGetattrResolveAlias: could not create file reference: "
-              "error %d\n", (int32)osStatus));
+      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.
@@ -1253,11 +1282,13 @@ HgfsGetattrResolveAlias(char const *fileName,       // IN:  Input filename
     * (HgfsGetattrFromName) will assume that an error means the file is a
     * regular file.
     */
+
    osStatus = FSResolveAliasFileWithMountFlags(&fileRef, FALSE, &targetIsFolder,
-                                               &wasAliased, kResolveAliasFileNoUI);
+                                               &wasAliased,
+                                               kResolveAliasFileNoUI);
    if (osStatus != noErr) {
-      LOG(4, ("HgfsGetattrResolveAlias: could not resolve reference: error "
-              "%d\n", (int32)osStatus));
+      LOG(4, ("%s: could not resolve reference: error %d\n",
+              __FUNCTION__, (int32)osStatus));
       goto exit;
    }
 
@@ -1274,37 +1305,38 @@ HgfsGetattrResolveAlias(char const *fileName,       // IN:  Input filename
        * and convert the CFURL to a basic UTF-8 string using a call to
        * CFURLGetFileSystemRepresentation().
        */
+
       resolvedRef = CFURLCreateFromFSRef(NULL, &fileRef);
       if (resolvedRef == NULL) {
-         LOG(4, ("HgfsGetattrResolveAlias: could not create resolved URL "
-                 "reference from resolved filesystem reference\n"));
+         LOG(4, ("%s: could not create resolved URL reference from "
+                 "resolved filesystem reference\n", __FUNCTION__));
          goto exit;
       }
       resolvedString = CFURLGetString(resolvedRef);
       if (resolvedString == NULL) {
-         LOG(4, ("HgfsGetattrResolveAlias: could not create resolved string "
-                 "reference from resolved URL reference\n"));
+         LOG(4, ("%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, ("HgfsGetattrResolveAlias: could not allocate %"FMTSZ"d bytes "
-                 "of memory for target name storage\n", maxPath));
+         LOG(4, ("%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, ("HgfsGetattrResolveAlias: could not convert and copy "
-                 "resolved URL reference into allocated buffer\n"));
+         LOG(4, ("%s: could not convert and copy resolved URL reference "
+                 "into allocated buffer\n", __FUNCTION__));
          goto exit;
       }
 
       *targetName = myTargetName;
-      LOG(4, ("HgfsGetattrResolveAlias: file was an alias\n"));
+      LOG(4, ("%s: file was an alias\n", __FUNCTION__));
    } else {
       *targetName = NULL;
-      LOG(4, ("HgfsGetattrResolveAlias: file was not an alias\n"));
+      LOG(4, ("%s: file was not an alias\n", __FUNCTION__));
    }
    status = 0;
 
@@ -1316,6 +1348,7 @@ HgfsGetattrResolveAlias(char const *fileName,       // IN:  Input filename
    if (resolvedRef != NULL) {
       CFRelease(resolvedRef);
    }
+
    return status;
 #endif
 }
@@ -1455,9 +1488,12 @@ HgfsConvertComponentCase(char *currentComponent,           // IN
 
       /*
        * Unicode_CompareIgnoreCase crashes with invalid unicode strings,
-       * validate and convert it appropriately before passing it to Unicode_* functions.
+       * validate and convert it appropriately before passing it to Unicode_*
+       * functions.
        */
-      if (!Unicode_IsBufferValid(dentryName, dentryNameLen, STRING_ENCODING_DEFAULT)) {
+
+      if (!Unicode_IsBufferValid(dentryName, dentryNameLen,
+                                 STRING_ENCODING_DEFAULT)) {
          /* Invalid unicode string, skip the entry. */
          continue;
       }
@@ -1472,11 +1508,13 @@ HgfsConvertComponentCase(char *currentComponent,           // IN
           * The current directory entry is a case insensitive match to
           * the specified component. Malloc and copy the current directory entry.
           */
+
          myConvertedComponentSize = dentryNameLen + 1;
          myConvertedComponent = malloc(myConvertedComponentSize);
          if (myConvertedComponent == NULL) {
             ret = errno;
-            LOG(4, ("%s: failed to malloc myConvertedComponent.\n", __FUNCTION__));
+            LOG(4, ("%s: failed to malloc myConvertedComponent.\n",
+                    __FUNCTION__));
             goto exit;
          }
          Str_Strcpy(myConvertedComponent, dentryName, myConvertedComponentSize);
@@ -1535,19 +1573,21 @@ HgfsConstructConvertedPath(char **path,                 // IN/OUT
    ASSERT(convertedPath);
    ASSERT(pathSize);
 
-   p = realloc(*path, *pathSize + convertedPathLen + sizeof(DIRSEPC));
+   p = realloc(*path, *pathSize + convertedPathLen + sizeof (DIRSEPC));
    if (!p) {
       int error = errno;
       LOG(4, ("%s: failed to realloc.\n", __FUNCTION__));
+
       return error;
    }
 
    *path = p;
-   *pathSize += convertedPathLen + sizeof(DIRSEPC);
+   *pathSize += convertedPathLen + sizeof (DIRSEPC);
 
    /* Copy out the converted component to curDir, and free it. */
-   Str_Strncat(p, *pathSize, DIRSEPS, sizeof(DIRSEPS));
+   Str_Strncat(p, *pathSize, DIRSEPS, sizeof (DIRSEPS));
    Str_Strncat(p, *pathSize, convertedPath, convertedPathLen);
+
    return 0;
 }
 
@@ -1613,6 +1653,7 @@ HgfsCaseInsensitiveLookup(const char *sharePath,           // IN
       } else {
          *convertedFileNameLength = strlen(fileName);
       }
+
       return 0;
    }
 
@@ -1761,16 +1802,22 @@ HgfsServerConvertCase(const char *sharePath,              // IN
     * and file is inaccessible using the case passed to us. We use access(2)
     * call to check if the passed case of the file name is correct.
     */
-   if (caseFlags == HGFS_FILE_NAME_CASE_INSENSITIVE && access(fileName, F_OK) == -1) {
+
+   if (caseFlags == HGFS_FILE_NAME_CASE_INSENSITIVE &&
+       access(fileName, F_OK) == -1) {
       LOG(4, ("%s: Case insensitive lookup, fileName: %s, flags: %u.\n",
               __FUNCTION__, fileName, caseFlags));
+
       error = HgfsCaseInsensitiveLookup(sharePath, sharePathLength,
                                         fileName, fileNameLength,
-                                        convertedFileName, convertedFileNameLength);
+                                        convertedFileName,
+                                        convertedFileNameLength);
+
       /*
-       * Success or non-ENOENT error code. HgfsCaseInsensitiveLookup can return ENOENT,
-       * and its ok to continue if it is ENOENT.
+       * Success or non-ENOENT error code. HgfsCaseInsensitiveLookup can
+       * return ENOENT, and its ok to continue if it is ENOENT.
        */
+
       switch (error) {
          case ENOENT:
             nameStatus = HGFS_NAME_STATUS_COMPLETE;
@@ -1782,6 +1829,7 @@ HgfsServerConvertCase(const char *sharePath,              // IN
             nameStatus = HGFS_NAME_STATUS_FAILURE;
             break;
       }
+
       return nameStatus;
    }
 
@@ -1792,6 +1840,7 @@ HgfsServerConvertCase(const char *sharePath,              // IN
    } else {
       *convertedFileNameLength = fileNameLength;
    }
+
    return nameStatus;
 }
 
@@ -2103,7 +2152,7 @@ HgfsGetattrFromName(char *fileName,                    // IN/OUT:  Input filenam
    ASSERT(fileName);
    ASSERT(attr);
 
-   LOG(4, ("HgfsGetattrFromName: getting attrs for \"%s\"\n", fileName));
+   LOG(4, ("%s: getting attrs for \"%s\"\n", __FUNCTION__, fileName));
 
    error = HgfsStat(fileName,
                     HgfsServerPolicy_IsShareOptionSet(configOptions,
@@ -2112,8 +2161,7 @@ HgfsGetattrFromName(char *fileName,                    // IN/OUT:  Input filenam
                     &creationTime);
    if (error) {
       status = errno;
-      LOG(4, ("HgfsGetattrFromName: error stating file: %s\n",
-              strerror(status)));
+      LOG(4, ("%s: error stating file: %s\n", __FUNCTION__, strerror(status)));
       goto exit;
    }
 
@@ -2122,23 +2170,25 @@ HgfsGetattrFromName(char *fileName,                    // IN/OUT:  Input filenam
     * regular files, directories, and symlinks. On Mac OS, we'll additionally
     * treat finder aliases as symlinks.
     */
+
    if (S_ISDIR(stats.st_mode)) {
       attr->type = HGFS_FILE_TYPE_DIRECTORY;
-      LOG(4, ("HgfsGetattrFromName: is a directory\n"));
+      LOG(4, ("%s: is a directory\n", __FUNCTION__));
    } else if (S_ISLNK(stats.st_mode)) {
       attr->type = HGFS_FILE_TYPE_SYMLINK;
-      LOG(4, ("HgfsGetattrFromName: is a symlink\n"));
+      LOG(4, ("%s: is a symlink\n", __FUNCTION__));
 
       /*
        * In the case of a symlink, we should populate targetName if the
        * caller asked. Use st_size and readlink() to do so.
        */
+
       if (targetName != NULL) {
 
          myTargetName = Posix_ReadLink(fileName);
          if (myTargetName == NULL) {
             error = errno;
-            LOG(4, ("HgfsGetattrFromName: readlink returned wrong size\n"));
+            LOG(4, ("%s: readlink returned wrong size\n", __FUNCTION__));
 
             /*
              * Because of an unavoidable race between the lstat(2) and the
@@ -2146,6 +2196,7 @@ HgfsGetattrFromName(char *fileName,                    // IN/OUT:  Input filenam
              * not have read the entire link. If that happens, just return
              * "out of memory".
              */
+
             status = error ? error : ENOMEM;
             goto exit;
          }
@@ -2163,20 +2214,22 @@ HgfsGetattrFromName(char *fileName,                    // IN/OUT:  Input filenam
        *
        * http://lists.apple.com/archives/carbon-development/2001/Nov/msg00007.html
        */
-      LOG(4, ("HgfsGetattrFromName: NOT a directory or symlink\n"));
+
+      LOG(4, ("%s: NOT a directory or symlink\n", __FUNCTION__));
       if (HgfsGetattrResolveAlias(fileName, &myTargetName)) {
-         LOG(4, ("HgfsGetattrFromName: could not resolve file aliases\n"));
+         LOG(4, ("%s: could not resolve file aliases\n", __FUNCTION__));
       }
       attr->type = HGFS_FILE_TYPE_REGULAR;
       if (myTargetName != NULL) {
          /*
-          * At this point the alias target has been successfully resolved. If the alias
-          * target is inside the same shared folder then convert it to relative path.
-          * Converting to a relative path produces a symlink that points to the target
-          * file in the guest OS.
-          * If the target lies outside the shared folder then treat it the same way as
-          * if alias has not been resolved.
+          * At this point the alias target has been successfully resolved. If
+          * the alias target is inside the same shared folder then convert it
+          * to relative path. Converting to a relative path produces a symlink
+          * that points to the target file in the guest OS. If the target lies
+          * outside the shared folder then treat it the same way as if alias
+          * has not been resolved.
           */
+
          HgfsNameStatus nameStatus;
          size_t sharePathLen;
          const char* sharePath;
@@ -2194,19 +2247,21 @@ HgfsGetattrFromName(char *fileName,                    // IN/OUT:  Input filenam
             myTargetName = relativeName;
             if (myTargetName != NULL) {
                /*
-                * Let's mangle the permissions and size of the file so that it more
-                * closely resembles a symlink. The size should be the length of the
-                * target name (not including the nul-terminator), and the permissions
-                * should be 777.
+                * Let's mangle the permissions and size of the file so that
+                * it more closely resembles a symlink. The size should be
+                * the length of the target name (not including the
+                * nul-terminator), and the permissions should be 777.
                 */
+
                stats.st_size = strlen(myTargetName);
                stats.st_mode |= ACCESSPERMS;
                attr->type = HGFS_FILE_TYPE_SYMLINK;
             } else {
-               LOG(4, ("HgfsGetattrFromName: out of memory\n"));
+               LOG(4, ("%s: out of memory\n", __FUNCTION__));
             }
          } else {
-             LOG(4, ("HgfsGetattrFromName: alias target is outside shared folder\n"));
+             LOG(4, ("%s: alias target is outside shared folder\n",
+                     __FUNCTION__));
          }
       }
    }
@@ -2218,12 +2273,11 @@ HgfsGetattrFromName(char *fileName,                    // IN/OUT:  Input filenam
        * (precomposed) so Mac hosts must convert from normal form D
        * (decomposed).
        */
-      if (!CodeSet_Utf8FormDToUtf8FormC(myTargetName,
-                                        strlen(myTargetName),
-                                        targetName,
-                                        NULL)) {
-         LOG(4, ("HgfsGetattrFromName: Unable to normalize form C "
-                 "\"%s\"\n", myTargetName));
+
+      if (!CodeSet_Utf8FormDToUtf8FormC(myTargetName, strlen(myTargetName),
+                                        targetName, NULL)) {
+         LOG(4, ("%s: Unable to normalize form C \"%s\"\n",
+                 __FUNCTION__, myTargetName));
          status = HgfsConvertFromNameStatus(HGFS_NAME_STATUS_FAILURE);
          goto exit;
       }
@@ -2299,11 +2353,11 @@ HgfsGetattrFromFd(int fd,                     // IN:  file descriptor
    ASSERT(attr);
    ASSERT(session);
 
-   LOG(4, ("HgfsGetattrFromFd: getting attrs for %u\n", fd));
+   LOG(4, ("%s: getting attrs for %u\n", __FUNCTION__, fd));
 
    error = HgfsFStat(fd, &stats, &creationTime);
    if (error) {
-      LOG(4, ("HgfsGetattrFromFd: error stating file: %s\n", strerror(error)));
+      LOG(4, ("%s: error stating file: %s\n", __FUNCTION__, strerror(error)));
       status = error;
       goto exit;
    }
@@ -2312,16 +2366,17 @@ HgfsGetattrFromFd(int fd,                     // IN:  file descriptor
     * For now, everything that isn't a directory or symlink is a regular
     * file.
     */
+
    if (S_ISDIR(stats.st_mode)) {
       attr->type = HGFS_FILE_TYPE_DIRECTORY;
-      LOG(4, ("HgfsGetattrFromFd: is a directory\n"));
+      LOG(4, ("%s: is a directory\n", __FUNCTION__));
    } else if (S_ISLNK(stats.st_mode)) {
       attr->type = HGFS_FILE_TYPE_SYMLINK;
-      LOG(4, ("HgfsGetattrFromFd: is a symlink\n"));
+      LOG(4, ("%s: is a symlink\n", __FUNCTION__));
 
    } else {
       attr->type = HGFS_FILE_TYPE_REGULAR;
-      LOG(4, ("HgfsGetattrFromFd: NOT a directory or symlink\n"));
+      LOG(4, ("%s: NOT a directory or symlink\n", __FUNCTION__));
    }
 
    HgfsStatToFileAttr(&stats, &creationTime, attr);
@@ -2337,22 +2392,20 @@ HgfsGetattrFromFd(int fd,                     // IN:  file descriptor
     */
 
    if (!HgfsFileDesc2Handle(fd, session, &handle)) {
-      LOG(4, ("HgfsGetattrFromFd: could not get HGFS handle for fd %u\n",
-              fd));
+      LOG(4, ("%s: could not get HGFS handle for fd %u\n", __FUNCTION__, fd));
       status = EBADF;
       goto exit;
    }
 
    if (!HgfsHandle2ShareMode(handle, session, &shareMode)) {
-      LOG(4, ("HgfsGetattrFromFd: could not get share mode fd %u\n",
-              fd));
+      LOG(4, ("%s: could not get share mode fd %u\n", __FUNCTION__, fd));
       status = EBADF;
       goto exit;
    }
 
    if (!HgfsHandle2FileName(handle, session, &fileName, &fileNameLen)) {
-      LOG(4, ("HgfsGetattrFromFd: could not map cached target file handle %u\n",
-              handle));
+      LOG(4, ("%s: could not map cached target file handle %u\n",
+              __FUNCTION__, handle));
       status = EBADF;
       goto exit;
    }
@@ -2361,14 +2414,15 @@ HgfsGetattrFromFd(int fd,                     // IN:  file descriptor
     * In the case we have a Windows client, force the hidden flag.
     * This will be ignored by Linux, Solaris clients.
     */
-   HgfsGetHiddenAttr(fileName, attr);
 
+   HgfsGetHiddenAttr(fileName, attr);
 
    if (shareMode == HGFS_OPEN_MODE_READ_ONLY) {
       /*
        * Share does not allow write, so tell the client
        * everything is read only.
        */
+
       if (attr->mask & HGFS_ATTR_VALID_OWNER_PERMS) {
          attr->ownerPerms &= ~HGFS_PERM_WRITE;
       }
@@ -2382,6 +2436,7 @@ HgfsGetattrFromFd(int fd,                     // IN:  file descriptor
 
 exit:
    free(fileName);
+
    return status;
 }
 
@@ -2454,7 +2509,7 @@ HgfsStatToFileAttr(struct stat *stats,       // IN: stat information
    attr->ownerPerms     = (stats->st_mode & S_IRWXU) >> 6;
    attr->groupPerms     = (stats->st_mode & S_IRWXG) >> 3;
    attr->otherPerms     = stats->st_mode & S_IRWXO;
-   LOG(4, ("HgfsStatToFileAttr: done, permissions %o%o%o%o, size %"FMT64"u\n",
+   LOG(4, ("%s: done, permissions %o%o%o%o, size %"FMT64"u\n", __FUNCTION__,
            attr->specialPerms, attr->ownerPerms, attr->groupPerms,
            attr->otherPerms, attr->size));
 #ifdef __FreeBSD__
@@ -2653,8 +2708,9 @@ HgfsSetattrTimes(struct stat *statBuf,       // IN: stat info
           != (HGFS_ATTR_VALID_ACCESS_TIME | HGFS_ATTR_VALID_WRITE_TIME)) {
 
          /*
-         * XXX Set also usec from nsec stat fields.
-         */
+          * XXX Set also usec from nsec stat fields.
+          */
+
          accessTime->tv_sec = statBuf->st_atime;
          accessTime->tv_usec = 0;
          modTime->tv_sec = statBuf->st_mtime;
@@ -2667,6 +2723,7 @@ HgfsSetattrTimes(struct stat *statBuf,       // IN: stat info
        * the guest time, and alwaysUseHostTime will be TRUE if the config
        * option to always use host time is set.
        */
+
       if (attr->mask & HGFS_ATTR_VALID_ACCESS_TIME) {
          if (!alwaysUseHostTime && (hints & HGFS_ATTR_HINT_SET_ACCESS_TIME)) {
             /* Use the guest-provided time */
@@ -2681,7 +2738,7 @@ HgfsSetattrTimes(struct stat *statBuf,       // IN: stat info
 
             if (gettimeofday(&tv, NULL) != 0) {
                error = errno;
-               LOG(4, ("HgfsSetattrTimes: gettimeofday error: %s\n",
+               LOG(4, ("%s: gettimeofday error: %s\n", __FUNCTION__,
                        strerror(error)));
                status = error;
                goto exit;
@@ -2704,7 +2761,7 @@ HgfsSetattrTimes(struct stat *statBuf,       // IN: stat info
 
             if (gettimeofday(&tv, NULL) != 0) {
                error = errno;
-               LOG(4, ("HgfsSetattrTimes: gettimeofday error: %s\n",
+               LOG(4, ("%s: gettimeofday error: %s\n", __FUNCTION__,
                        strerror(error)));
                status = error;
                goto exit;
@@ -2764,13 +2821,12 @@ HgfsSetattrFromFd(HgfsHandle file,          // IN: file descriptor
 
    status = HgfsGetFd(file, session, FALSE, &fd);
    if (status != 0) {
-      LOG(4, ("HgfsSetattrFromFd: Could not get file descriptor\n"));
+      LOG(4, ("%s: Could not get file descriptor\n", __FUNCTION__));
       goto exit;
    }
 
    if (!HgfsHandle2ShareMode(file, session, &shareMode)) {
-      LOG(4, ("HgfsSetattrFromFd: could not get share mode fd %u\n",
-              fd));
+      LOG(4, ("%s: could not get share mode fd %u\n", __FUNCTION__, fd));
       status = EBADF;
       goto exit;
    }
@@ -2783,7 +2839,7 @@ HgfsSetattrFromFd(HgfsHandle file,          // IN: file descriptor
    /* We need the old stats so that we can preserve times. */
    if (fstat(fd, &statBuf) == -1) {
       error = errno;
-      LOG(4, ("HgfsSetattrFromFd: error stating file %u: %s\n",
+      LOG(4, ("%s: error stating file %u: %s\n", __FUNCTION__, 
               fd, strerror(error)));
       status = error;
       goto exit;
@@ -2802,12 +2858,14 @@ HgfsSetattrFromFd(HgfsHandle file,          // IN: file descriptor
     * toggle permsChanged since it should not influence our decision of
     * whether to actually call chmod or not.
     */
+
    permsChanged = HgfsSetattrMode(&statBuf, attr, &newPermissions);
    if (permsChanged) {
-      LOG(4, ("HgfsSetattrFromFd: set mode %o\n", (unsigned)newPermissions));
+      LOG(4, ("%s: set mode %o\n", __FUNCTION__, (unsigned)newPermissions));
+
       if (fchmod(fd, newPermissions) < 0) {
          error = errno;
-         LOG(4, ("HgfsSetattrFromFd: error chmoding file %u: %s\n",
+         LOG(4, ("%s: error chmoding file %u: %s\n", __FUNCTION__,
                  fd, strerror(error)));
          status = error;
       }
@@ -2815,38 +2873,38 @@ HgfsSetattrFromFd(HgfsHandle file,          // IN: file descriptor
 
    idChanged = HgfsSetattrOwnership(attr, &newUid, &newGid);
    if (idChanged) {
-      LOG(4, ("HgfsSetattrFromFd: set uid %"FMTUID" and gid %"FMTUID"\n",
+      LOG(4, ("%s: set uid %"FMTUID" and gid %"FMTUID"\n", __FUNCTION__,
               newUid, newGid));
       if (fchown(fd, newUid, newGid) < 0) {
          error = errno;
-         LOG(4, ("HgfsSetattrFromFd: error chowning file %u: %s\n",
+         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
        * should have predicted this and removed the oplock prior to sending
        * the truncate request. At this point, the server must safeguard itself
        * against deadlock.
        */
+
       if (!HgfsHandle2ServerLock(file, session, &serverLock)) {
-         LOG(4, ("HgfsSetattrFromFd: File handle is no longer valid.\n"));
+         LOG(4, ("%s: File handle is no longer valid.\n", __FUNCTION__));
          status = EBADF;
       } else if (serverLock != HGFS_LOCK_NONE) {
-         LOG(4, ("HgfsSetattrFromFd: Client attempted to truncate an "
-                  "oplocked file\n"));
+         LOG(4, ("%s: Client attempted to truncate an oplocked file\n",
+                 __FUNCTION__));
          status = EBUSY;
       } else if (ftruncate(fd, attr->size) < 0) {
          error = errno;
-         LOG(4, ("HgfsSetattrFromFd: error truncating file %u: %s\n",
+         LOG(4, ("%s: error truncating file %u: %s\n", __FUNCTION__,
                  fd, strerror(error)));
          status = error;
       } else {
-         LOG(4, ("HgfsSetattrFromFd: set size %"FMT64"u\n", attr->size));
+         LOG(4, ("%s: set size %"FMT64"u\n", __FUNCTION__, attr->size));
       }
    }
 
@@ -2864,7 +2922,7 @@ HgfsSetattrFromFd(HgfsHandle file,          // IN: file descriptor
    if (timesStatus == 0 && timesChanged) {
       uid_t uid;
 
-      LOG(4, ("HgfsSetattrFromFd: setting new times\n"));
+      LOG(4, ("%s: setting new times\n", __FUNCTION__));
 
       /*
        * If the VMX is either the file owner or running as root, switch to
@@ -2873,8 +2931,8 @@ HgfsSetattrFromFd(HgfsHandle file,          // IN: file descriptor
        */
 
       if (!Id_IsSuperUser() && (getuid() != statBuf.st_uid)) {
-         LOG(4, ("HgfsSetattrFromFd: only owner of file %u or root can call "
-                 "futimes\n", fd));
+         LOG(4, ("%s: only owner of file %u or root can call futimes\n",
+                 __FUNCTION__, fd));
          /* XXX: Linux kernel says both EPERM and EACCES are valid here. */
          status = EPERM;
          goto exit;
@@ -2887,7 +2945,7 @@ HgfsSetattrFromFd(HgfsHandle file,          // IN: file descriptor
 
       if (futimes(fd, times) < 0) {
          error = errno;
-         LOG(4, ("HgfsSetattrFromFd: futimes error on file %u: %s\n",
+         LOG(4, ("%s: futimes error on file %u: %s\n", __FUNCTION__,
                  fd, strerror(error)));
          status = error;
       }
@@ -2940,14 +2998,11 @@ HgfsSetattrFromName(char *cpName,             // IN: Name
    HgfsServerLock serverLock;
    HgfsShareOptions configOptions;
 
-   nameStatus = HgfsServerGetAccess(cpName,
-                                    cpNameSize,
-                                    HGFS_OPEN_MODE_WRITE_ONLY,
-                                    caseFlags,
-                                    &localName,
-                                    NULL);
+   nameStatus = HgfsServerGetAccess(cpName, cpNameSize,
+                                    HGFS_OPEN_MODE_WRITE_ONLY, caseFlags,
+                                    &localName, NULL);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsSetattrFromName: access check failed\n"));
+      LOG(4, ("%s: access check failed\n", __FUNCTION__));
       status = HgfsConvertFromNameStatus(nameStatus);
       goto exit;
    }
@@ -2958,33 +3013,35 @@ HgfsSetattrFromName(char *cpName,             // IN: Name
    nameStatus = HgfsServerPolicy_GetShareOptions(cpName, cpNameSize,
                                                  &configOptions);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsSetattrFromName: no matching share: %s.\n", cpName));
+      LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, cpName));
       goto exit;
    }
 
-   if (!HgfsServerPolicy_IsShareOptionSet(configOptions, HGFS_SHARE_FOLLOW_SYMLINKS)) {
+   if (!HgfsServerPolicy_IsShareOptionSet(configOptions,
+                                          HGFS_SHARE_FOLLOW_SYMLINKS)) {
       /*
        * If followSymlink option is not set, verify that the pathname isn't a
-       * symlink. Some of the following syscalls (chmod, for example) will follow
-       * a link. So we need to verify the final component too. The parent has
-       * already been verified in HgfsServerGetAccess.
+       * symlink. Some of the following syscalls (chmod, for example) will
+       * follow a link. So we need to verify the final component too. The
+       * parent has already been verified in HgfsServerGetAccess.
        *
        * XXX: This is racy. But clients interested in preventing a race should
        * have sent us a Setattr packet with a valid HGFS handle.
        */
+
       if (File_IsSymLink(localName)) {
-         LOG(4, ("HgfsSetattrFromName: pathname contains a symlink\n"));
+         LOG(4, ("%s: pathname contains a symlink\n", __FUNCTION__));
          status = EINVAL;
          goto exit_free;
       }
    }
 
-   LOG(4, ("HgfsSetattrFromName: setting attrs for \"%s\"\n", localName));
+   LOG(4, ("%s: setting attrs for \"%s\"\n", __FUNCTION__, localName));
 
    /* We need the old stats so that we can preserve times. */
    if (Posix_Lstat(localName, &statBuf) == -1) {
       error = errno;
-      LOG(4, ("HgfsSetattrFromName: error stating file \"%s\": %s\n",
+      LOG(4, ("%s: error stating file \"%s\": %s\n", __FUNCTION__, 
               localName, strerror(error)));
       status = error;
       goto exit_free;
@@ -3003,26 +3060,30 @@ HgfsSetattrFromName(char *cpName,             // IN: Name
     * toggle permsChanged since it should not influence our decision of
     * whether to actually call chmod or not.
     */
+
    permsChanged = HgfsSetattrMode(&statBuf, attr, &newPermissions);
    if (permsChanged) {
-      LOG(4, ("HgfsSetattrFromName: set mode %o\n", (unsigned)newPermissions));
+      LOG(4, ("%s: set mode %o\n", __FUNCTION__, (unsigned)newPermissions));
+
       if (Posix_Chmod(localName, newPermissions) < 0) {
          error = errno;
-         LOG(4, ("HgfsSetattrFromName: error chmoding file \"%s\": %s\n",
+         LOG(4, ("%s: error chmoding file \"%s\": %s\n", __FUNCTION__,
                  localName, strerror(error)));
          status = error;
       }
    }
 
    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, ("HgfsSetattrFromName: error chowning file \"%s\": %s\n",
+         LOG(4, ("%s: error chowning file \"%s\": %s\n", __FUNCTION__,
                  localName, strerror(error)));
          status = error;
       }
@@ -3035,17 +3096,18 @@ HgfsSetattrFromName(char *cpName,             // IN: Name
        * the truncate request. At this point, the server must safeguard itself
        * against deadlock.
        */
+
       if (HgfsFileHasServerLock(localName, session, &serverLock, &fd)) {
-         LOG(4, ("HgfsSetattrFromName: Client attempted to truncate an "
-                  "oplocked file\n"));
+         LOG(4, ("%s: Client attempted to truncate an oplocked file\n",
+                 __FUNCTION__));
          status = EBUSY;
       } else if (Posix_Truncate(localName, attr->size) < 0) {
          error = errno;
-         LOG(4, ("HgfsSetattrFromName: error truncating file \"%s\": %s\n",
+         LOG(4, ("%s: error truncating file \"%s\": %s\n", __FUNCTION__,
                  localName, strerror(error)));
          status = error;
       } else {
-         LOG(4, ("HgfsSetattrFromName: set size %"FMT64"u\n", attr->size));
+         LOG(4, ("%s: set size %"FMT64"u\n", __FUNCTION__, attr->size));
       }
    }
 
@@ -3056,7 +3118,6 @@ HgfsSetattrFromName(char *cpName,             // IN: Name
    timesStatus = HgfsSetattrTimes(&statBuf, attr, hints,
                              &times[0], &times[1], &timesChanged);
    if (timesStatus == 0 && timesChanged) {
-
       /*
        * XXX Newer glibc provide also lutimes() and futimes()
        *     when we politely ask with -D_GNU_SOURCE -D_BSD_SOURCE
@@ -3064,7 +3125,7 @@ HgfsSetattrFromName(char *cpName,             // IN: Name
 
       if (Posix_Utimes(localName, times) < 0) {
          error = errno;
-         LOG(4, ("HgfsSetattrFromName: utimes error on file \"%s\": %s\n",
+         LOG(4, ("%s: utimes error on file \"%s\": %s\n", __FUNCTION__,
                  localName, strerror(error)));
          status = error;
       }
@@ -3074,6 +3135,7 @@ HgfsSetattrFromName(char *cpName,             // IN: Name
 
 exit_free:
    free(localName);
+
 exit:
    return status;
 }
@@ -3128,7 +3190,7 @@ HgfsServerScandir(char const *baseDir,      // IN: Directory to search in
    result = Posix_Open(baseDir, openFlags);
    if (result < 0) {
       status = errno;
-      LOG(4, ("HgfsServerScandir: error in open: %d (%s)\n", status,
+      LOG(4, ("%s: error in open: %d (%s)\n", __FUNCTION__, status, 
               strerror(status)));
       goto exit;
    }
@@ -3138,8 +3200,7 @@ HgfsServerScandir(char const *baseDir,      // IN: Directory to search in
     * Rather than read a single dent at a time, batch up multiple dents
     * in each call by using a buffer substantially larger than one dent.
     */
-   while ((result = getdents(fd, (void *)buffer,
-                             sizeof buffer)) > 0) {
+   while ((result = getdents(fd, (void *)buffer, sizeof buffer)) > 0) {
       size_t offset = 0;
       while (offset < result) {
          DirectoryEntry *newDent, **newDents;
@@ -3161,14 +3222,13 @@ HgfsServerScandir(char const *baseDir,      // IN: Directory to search in
           * Allocate the new dent and set it up. We do a straight memcpy of
           * the entire record to avoid dealing with platform-specific fields.
           */
+
          myDents[myNumDents] = malloc(newDent->d_reclen);
          if (myDents[myNumDents] == NULL) {
             status = ENOMEM;
             goto exit;
          }
          memcpy(myDents[myNumDents], newDent, newDent->d_reclen);
-         HgfsEscape_Undo(myDents[myNumDents]->d_name,
-                         strlen(myDents[myNumDents]->d_name)+ 1);
 
          /*
           * Dent is done. Bump the offset to the batched buffer to process the
@@ -3181,7 +3241,7 @@ HgfsServerScandir(char const *baseDir,      // IN: Directory to search in
 
    if (result == -1) {
       status = errno;
-      LOG(4, ("HgfsServerScandir: error in getdents: %d (%s)\n", status,
+      LOG(4, ("%s: error in getdents: %d (%s)\n", __FUNCTION__, status, 
               strerror(status)));
       goto exit;
    }
@@ -3189,7 +3249,7 @@ HgfsServerScandir(char const *baseDir,      // IN: Directory to search in
   exit:
    if (fd != -1 && close(fd) < 0) {
       status = errno;
-      LOG(4, ("HgfsServerScandir: error in close: %d (%s)\n", status,
+      LOG(4, ("%s: error in close: %d (%s)\n", __FUNCTION__, status,
               strerror(status)));
    }
 
@@ -3197,6 +3257,7 @@ HgfsServerScandir(char const *baseDir,      // IN: Directory to search in
     * On error, free all allocated dents. On success, set the dents pointer
     * given to us by the client.
     */
+
    if (status != 0) {
       size_t i;
       for (i = 0; i < myNumDents; i++) {
@@ -3298,27 +3359,23 @@ HgfsServerOpen(char const *packetIn,     // IN: incoming packet
 
    /* HGFS_OPEN_VALID_FILE_NAME is checked in the unpack function. */
    if (!(openInfo.mask & HGFS_OPEN_VALID_MODE)) {
-      LOG(4, ("HgfsServerOpen: filename or mode not provided\n"));
+      LOG(4, ("%s: filename or mode not provided\n", __FUNCTION__));
       status = EINVAL;
       goto exit;
    }
 
-   nameStatus = HgfsServerGetAccess(openInfo.cpName,
-                                    openInfo.cpNameSize,
-                                    openInfo.mode,
-                                    openInfo.caseFlags,
-                                    &localName,
-                                    NULL);
+   nameStatus = HgfsServerGetAccess(openInfo.cpName, openInfo.cpNameSize,
+                                    openInfo.mode, openInfo.caseFlags,
+                                    &localName, NULL);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsServerOpen: access check failed\n"));
+      LOG(4, ("%s: access check failed\n", __FUNCTION__));
       status = HgfsConvertFromNameStatus(nameStatus);
       goto exit;
    }
 
    if (openInfo.mask & HGFS_OPEN_VALID_FLAGS) {
       savedOpenFlags = openInfo.flags;
-      if (!HgfsServerCheckOpenFlagsForShare(&openInfo,
-                                            &openInfo.flags)) {
+      if (!HgfsServerCheckOpenFlagsForShare(&openInfo, &openInfo.flags)) {
          /* Incompatible open mode with share mode. */
          status = EACCES;
          goto exit;
@@ -3328,8 +3385,8 @@ HgfsServerOpen(char const *packetIn,     // IN: incoming packet
    ASSERT(localName);
    openInfo.utf8Name = localName;
 
-   LOG(4, ("HgfsServerOpen: opening \"%s\", mode %u, flags %u, perms "
-           "%u%u%u%u\n", openInfo.utf8Name,
+   LOG(4, ("%s: opening \"%s\", mode %u, flags %u, perms %u%u%u%u\n",
+           __FUNCTION__, openInfo.utf8Name,
            (openInfo.mask & HGFS_OPEN_VALID_MODE) ? openInfo.mode : 0,
            (openInfo.mask & HGFS_OPEN_VALID_FLAGS) ? openInfo.flags : 0,
            (openInfo.mask & HGFS_OPEN_VALID_SPECIAL_PERMS) ?
@@ -3356,9 +3413,10 @@ HgfsServerOpen(char const *packetIn,     // IN: incoming packet
     * since that won't break a shared oplock, but the clients should already
     * realize that the second open can be avoided via sharing handles, too.
     */
+
    if (HgfsFileHasServerLock(localName, session, &serverLock, &newFd)) {
-      LOG (4, ("HgfsServerOpen: Client tried to open new handle for oplocked "
-               "file %s.\n", localName));
+      LOG (4, ("%s: Client tried to open new handle for oplocked file %s.\n",
+               __FUNCTION__, localName));
       status = EBUSY;
       goto exit;
    }
@@ -3368,7 +3426,7 @@ HgfsServerOpen(char const *packetIn,     // IN: incoming packet
                                                  openInfo.cpNameSize,
                                                  &configOptions);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsServerSearchRead: no matching share: %s.\n", openInfo.cpName));
+      LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, openInfo.cpName));
       status = ENOENT;
       goto exit;
    }
@@ -3377,7 +3435,8 @@ HgfsServerOpen(char const *packetIn,     // IN: incoming packet
                                                       HGFS_SHARE_FOLLOW_SYMLINKS);
 
    /* See if the name is valid, and if so add it and return the handle. */
-   status = HgfsValidateOpen(&openInfo, followSymlinks, session, &localId, &newFd);
+   status = HgfsValidateOpen(&openInfo, followSymlinks, session, &localId,
+                             &newFd);
    if (status == 0) {
       ASSERT(newFd >= 0);
 
@@ -3385,12 +3444,15 @@ HgfsServerOpen(char const *packetIn,     // IN: incoming packet
        * Open succeeded, so make new node and return its handle. If we fail,
        * it's almost certainly an internal server error.
        */
-      if (!HgfsCreateAndCacheFileNode(&openInfo, &localId, newFd, FALSE, session)) {
+
+      if (!HgfsCreateAndCacheFileNode(&openInfo, &localId, newFd, FALSE,
+                                      session)) {
          status = HGFS_INTERNAL_STATUS_ERROR;
          goto exit;
       }
 
-      if (HgfsPackOpenReply(packetIn, status, &openInfo, &packetOut, &packetOutSize)) {
+      if (HgfsPackOpenReply(packetIn, status, &openInfo, &packetOut,
+                            &packetOutSize)) {
          if (!HgfsPacketSend(packetOut, packetOutSize, session, 0)) {
             free(packetOut);
          }
@@ -3500,11 +3562,13 @@ HgfsServerRead(char const *packetIn,     // IN: incoming packet
        * requiredSize is user-provided, so this test must be carefully
        * written to prevent wraparounds.
        */
+
       if (requiredSize > extra) {
          /*
           * The client wants to read more bytes than our payload can handle.
           * Truncate the request
           */
+
          requiredSize = extra;
       }
 
@@ -3514,21 +3578,23 @@ HgfsServerRead(char const *packetIn,     // IN: incoming packet
       replyActualSize = &reply->actualSize;
    }
 
-   LOG(4, ("HgfsServerRead: read fh %u, offset %"FMT64"u, count %u\n",
+   LOG(4, ("%s: read fh %u, offset %"FMT64"u, count %u\n", __FUNCTION__,
            file, offset, requiredSize));
 
    /* Get the file descriptor from the cache */
    status = HgfsGetFd(file, session, FALSE, &fd);
 
    if (status != 0) {
-      LOG(4, ("HgfsServerRead: Could not get file descriptor\n"));
+      LOG(4, ("%s: Could not get file descriptor\n", __FUNCTION__));
       free(packetOut);
+
       return status;
    }
 
    if (!HgfsHandleIsSequentialOpen(file, session, &sequentialOpen)) {
-      LOG(4, ("HgfsServerRead: Could not get sequenial open status\n"));
+      LOG(4, ("%s: Could not get sequenial open status\n", __FUNCTION__));
       free(packetOut);
+
       return EBADF;
    }
 
@@ -3544,7 +3610,8 @@ HgfsServerRead(char const *packetIn,     // IN: incoming packet
     * Seek to the offset and read from the file. Grab the IO lock to make
     * this and the subsequent read atomic.
     */
-   SyncMutex_Lock(&session->nodeArrayLock);
+
+   SyncMutex_Lock(&session->fileIOLock);
    if (!sequentialOpen) {
 #   ifdef linux
       {
@@ -3561,24 +3628,24 @@ HgfsServerRead(char const *packetIn,     // IN: incoming packet
 
       if (error < 0) {
          status = errno;
-         LOG(4, ("HgfsServerRead: could not seek to %"FMT64"u: %s\n",
+         LOG(4, ("%s: could not seek to %"FMT64"u: %s\n", __FUNCTION__,
                  offset, strerror(status)));
-         SyncMutex_Unlock(&session->nodeArrayLock);
+         SyncMutex_Unlock(&session->fileIOLock);
          goto error;
       }
    }
 
    error = read(fd, payload, requiredSize);
-   SyncMutex_Unlock(&session->nodeArrayLock);
+   SyncMutex_Unlock(&session->fileIOLock);
 #endif
    if (error < 0) {
       status = errno;
-      LOG(4, ("HgfsServerRead: error reading from file: %s\n",
+      LOG(4, ("%s: error reading from file: %s\n", __FUNCTION__,
               strerror(status)));
       goto error;
    }
 
-   LOG(4, ("HgfsServerRead: read %d bytes\n", error));
+   LOG(4, ("%s: read %d bytes\n", __FUNCTION__, error));
    *replyActualSize = error;
    replySize += error;
 
@@ -3590,9 +3657,6 @@ HgfsServerRead(char const *packetIn,     // IN: incoming packet
    return 0;
 
 error:
-   if (!HgfsRemoveFromCache(file, session)) {
-      LOG(4, ("HgfsServerRead: Could not remove the node from cache.\n"));
-   }
    free(packetOut);
    return status;
 }
@@ -3681,8 +3745,8 @@ HgfsServerWrite(char const *packetIn,     // IN: incoming packet
       actualSize = &reply->actualSize;
    }
 
-   LOG(4, ("HgfsServerWrite: write fh %u, offset %"FMT64"u, count %u, extra %u\n",
-           file, offset, requiredSize, extra));
+   LOG(4, ("%s: write fh %u, offset %"FMT64"u, count %u, extra %u\n",
+           __FUNCTION__, file, offset, requiredSize, extra));
 
    /* Get the file desriptor from the cache */
    status = HgfsGetFd(file, session, ((flags & HGFS_WRITE_APPEND) ?
@@ -3690,14 +3754,16 @@ HgfsServerWrite(char const *packetIn,     // IN: incoming packet
                       &fd);
 
    if (status != 0) {
-      LOG(4, ("HgfsServerWrite: Could not get file descriptor\n"));
+      LOG(4, ("%s: Could not get file descriptor\n", __FUNCTION__));
       free(packetOut);
+
       return status;
    }
 
    if (!HgfsHandleIsSequentialOpen(file, session, &sequentialOpen)) {
-      LOG(4, ("HgfsServerWrite: Could not get sequential open status\n"));
+      LOG(4, ("%s: Could not get sequential open status\n", __FUNCTION__));
       free(packetOut);
+
       return EBADF;
    }
 
@@ -3705,11 +3771,13 @@ HgfsServerWrite(char const *packetIn,     // IN: incoming packet
     * requiredSize is user-provided, so this test must be carefully
     * written to prevent wraparounds.
     */
+
    if (requiredSize > extra) {
       /*
        * The driver wants to write more bytes than there is in its payload.
        * Truncate the request
        */
+
       requiredSize = extra;
    }
 
@@ -3742,36 +3810,34 @@ HgfsServerWrite(char const *packetIn,     // IN: incoming packet
 
       if (error < 0) {
          status = errno;
-         LOG(4, ("HgfsServerWrite: could not seek to %"FMT64"u: %s\n",
+         LOG(4, ("%s: could not seek to %"FMT64"u: %s\n", __FUNCTION__,
                  offset, strerror(status)));
-         SyncMutex_Unlock(&session->nodeArrayLock);
+         SyncMutex_Unlock(&session->fileIOLock);
          goto error;
       }
    }
 
    error = write(fd, payload, requiredSize);
-   SyncMutex_Unlock(&session->nodeArrayLock);
+   SyncMutex_Unlock(&session->fileIOLock);
 #endif
    if (error < 0) {
       status = errno;
-      LOG(4, ("HgfsServerWrite: error writing to file: %s\n",
+      LOG(4, ("%s: error writing to file: %s\n", __FUNCTION__, 
               strerror(status)));
       goto error;
    }
 
-   LOG(4, ("HgfsServerWrite: wrote %d bytes\n", error));
+   LOG(4, ("%s: wrote %d bytes\n", __FUNCTION__, error));
    *actualSize = error;
    status = 0;
 
-   if (!HgfsPackAndSendPacket(packetOut, replySize, 0, header->id, session, 0)) {
+   if (!HgfsPackAndSendPacket(packetOut, replySize, 0, header->id,
+                              session, 0)) {
       goto error;
    }
    return 0;
 
 error:
-   if (!HgfsRemoveFromCache(file, session)) {
-      LOG(4, ("HgfsServerWrite: Could not remove the node from cache.\n"));
-   }
    free(packetOut);
    return status;
 }
@@ -3836,11 +3902,11 @@ HgfsServerSearchOpen(char const *packetIn,     // IN: incoming packet
       dirNameLength = requestV3->dirName.length;
       replySearch = &replyV3->search;
       replyV3->reserved = 0;
-      LOG(4, ("HgfsServerSearchOpen: HGFS_OP_SEARCH_OPEN_V3\n"));
+      LOG(4, ("%s: HGFS_OP_SEARCH_OPEN_V3\n", __FUNCTION__));
    } else {
       HgfsRequestSearchOpen *request = (HgfsRequestSearchOpen *)packetIn;
 
-      replySize = sizeof *request;
+      replySize = sizeof (HgfsReplySearchOpen);
       packetOut = Util_SafeMalloc(replySize);
 
       /* Enforced by the dispatch function */
@@ -3856,6 +3922,7 @@ HgfsServerSearchOpen(char const *packetIn,     // IN: incoming packet
     * request->dirName.length is user-provided, so this test must be carefully
     * written to prevent wraparounds.
     */
+
    if (dirNameLength > extra) {
       /* The input packet is smaller than the request */
       status = EPROTO;
@@ -3863,42 +3930,48 @@ HgfsServerSearchOpen(char const *packetIn,     // IN: incoming packet
    }
    /* It is now safe to read the dirName */
 
-   nameStatus = HgfsServerGetAccess(dirName,
-                                    dirNameLength,
+   nameStatus = HgfsServerGetAccess(dirName, dirNameLength,
                                     HGFS_OPEN_MODE_READ_ONLY,
-                                    caseFlags,
-                                    &baseDir,
-                                    &baseDirLen);
+                                    caseFlags, &baseDir, &baseDirLen);
    switch (nameStatus) {
    case HGFS_NAME_STATUS_COMPLETE:
    {
-      char const *inEnd;
+      char *inEnd;
       char *next;
       int len;
 
       ASSERT(baseDir);
-      LOG(4, ("HgfsServerSearchOpen: searching in \"%s\", %s.\n", baseDir, dirName));
+      LOG(4, ("%s: searching in \"%s\", %s.\n", __FUNCTION__, baseDir,
+              dirName));
 
       inEnd = dirName + dirNameLength;
 
       /* Get the first component. */
       len = CPName_GetComponent(dirName, inEnd, (char const **) &next);
       if (len < 0) {
-         LOG(4, ("HgfsServerSearchOpen: get first component failed\n"));
+         LOG(4, ("%s: get first component failed\n", __FUNCTION__));
          status = ENOENT;
          goto exit;
       }
 
-      LOG(4, ("HgfsServerSearchOpen: dirName: %s.\n", dirName));
+      if (*inEnd != '\0') {
+         /*
+          * NT4 clients can send the name without a nul-terminator.
+          * The space for the  nul is included and tested for in the size
+          * calculations above. Size of structure (includes a single
+          * character of the name) and the full dirname length.
+          */
+         *inEnd = '\0';
+      }
+
+      LOG(4, ("%s: dirName: %s.\n", __FUNCTION__, dirName));
       status = HgfsServerSearchRealDir(baseDir,
                                        baseDirLen,
                                        DIRECTORY_SEARCH_TYPE_DIR,
-                                       dirName,
-                                       session,
-                                       &handle);
+                                       dirName, session, &handle);
       free(baseDir);
       if (status != 0) {
-         LOG(4, ("HgfsServerSearchOpen: couldn't scandir\n"));
+         LOG(4, ("%s: couldn't scandir\n", __FUNCTION__));
          goto exit;
       }
       break;
@@ -3909,7 +3982,8 @@ HgfsServerSearchOpen(char const *packetIn,     // IN: incoming packet
        * This is the base of our namespace, so enumerate all
        * shares. [bac]
        */
-      LOG(4, ("HgfsServerSearchOpen: opened search on base\n"));
+
+      LOG(4, ("%s: opened search on base\n", __FUNCTION__));
       status = HgfsServerSearchVirtualDir(HgfsServerPolicy_GetShares,
                                           HgfsServerPolicy_GetSharesInit,
                                           HgfsServerPolicy_GetSharesCleanup,
@@ -3917,13 +3991,13 @@ HgfsServerSearchOpen(char const *packetIn,     // IN: incoming packet
                                           session,
                                           &handle);
       if (status != 0) {
-         LOG(4, ("HgfsServerSearchOpen: couldn't enumerate shares\n"));
+         LOG(4, ("%s: couldn't enumerate shares\n", __FUNCTION__));
          goto exit;
       }
       break;
 
    default:
-      LOG(4, ("HgfsServerSearchOpen: access check failed\n"));
+      LOG(4, ("%s: access check failed\n", __FUNCTION__));
       status = HgfsConvertFromNameStatus(nameStatus);
       goto exit;
    }
@@ -3936,9 +4010,11 @@ HgfsServerSearchOpen(char const *packetIn,     // IN: incoming packet
     * Return handle to the search object as the reply to the search
     * open.
     */
+
    *replySearch = handle;
 
-   if (!HgfsPackAndSendPacket(packetOut, replySize, 0, header->id, session, 0)) {
+   if (!HgfsPackAndSendPacket(packetOut, replySize, 0, header->id,
+                              session, 0)) {
       status = 0;
       goto exit;
    }
@@ -3946,6 +4022,7 @@ HgfsServerSearchOpen(char const *packetIn,     // IN: incoming packet
 
 exit:
    free(packetOut);
+
    return status;
 }
 
@@ -3986,20 +4063,16 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
    ASSERT(packetIn);
    ASSERT(session);
 
-   if (!HgfsUnpackSearchReadRequest(packetIn,
-                                    packetSize,
-                                    &attr,
-                                    &hgfsSearchHandle,
-                                    &requestedOffset)) {
+   if (!HgfsUnpackSearchReadRequest(packetIn, packetSize, &attr,
+                                    &hgfsSearchHandle, &requestedOffset)) {
       return EPROTO;
    }
 
-   LOG(4, ("HgfsServerSearchRead: read search #%u, offset %u\n",
+   LOG(4, ("%s: read search #%u, offset %u\n", __FUNCTION__,
            hgfsSearchHandle, requestedOffset));
 
    if (!HgfsGetSearchCopy(hgfsSearchHandle, session, &search)) {
-      LOG(4, ("HgfsServerSearchRead: handle %u is invalid\n",
-              hgfsSearchHandle));
+      LOG(4, ("%s: handle %u is invalid\n", __FUNCTION__, hgfsSearchHandle));
       return EBADF;
    }
 
@@ -4009,9 +4082,11 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
                                                     search.utf8ShareNameLen,
                                                     &configOptions);
       if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-         LOG(4, ("HgfsServerSearchRead: no matching share: %s.\n", search.utf8ShareName));
+         LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__,
+                 search.utf8ShareName));
          free(search.utf8Dir);
          free(search.utf8ShareName);
+
          return ENOENT;
       }
    }
@@ -4037,27 +4112,29 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
           * Construct the UTF8 version of the full path to the file, and call
           * HgfsGetattrFromName to get the attributes of the file.
           */
+
          fullNameLen = search.utf8DirLen + 1 + length;
          fullName = (char *)malloc(fullNameLen + 1);
          if (!fullName) {
-            LOG(4, ("HgfsServerSearchRead: could not allocate space for "
-                    "\"%s\\%s\"\n", search.utf8Dir, dent->d_name));
+            LOG(4, ("%s: could not allocate space for \"%s\\%s\"\n",
+                    __FUNCTION__, search.utf8Dir, dent->d_name));
             free(search.utf8Dir);
             free(search.utf8ShareName);
             free(dent);
+
             return ENOMEM;
          }
          memcpy(fullName, search.utf8Dir, search.utf8DirLen);
          fullName[search.utf8DirLen] = DIRSEPC;
          memcpy(&fullName[search.utf8DirLen + 1], dent->d_name, length + 1);
 
-         LOG(4, ("HgfsServerSearchRead: about to stat \"%s\"\n", fullName));
+         LOG(4, ("%s: about to stat \"%s\"\n", __FUNCTION__, fullName));
 
-         status = HgfsGetattrFromName(fullName, configOptions, search.utf8ShareName,
-                                      &attr, NULL);
+         status = HgfsGetattrFromName(fullName, configOptions,
+                                      search.utf8ShareName, &attr, NULL);
          if (status != 0) {
             HgfsOp savedOp = attr.requestType;
-            LOG(4, ("HgfsServerSearchRead: stat FAILED %s (%d)\n",
+            LOG(4, ("%s: stat FAILED %s (%d)\n", __FUNCTION__, 
                     fullName, status));
             memset(&attr, 0, sizeof attr);
             attr.requestType = savedOp;
@@ -4073,11 +4150,10 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
           * (precomposed) so Mac hosts must convert from normal form D
           * (decomposed).
           */
-         if (!CodeSet_Utf8FormDToUtf8FormC((const char *)dent->d_name,
-                                           length,
-                                           &entryName,
-                                           &entryNameLen)) {
-            LOG(4, ("HgfsServerSearchRead: Unable to normalize form C \"%s\"\n",
+
+         if (!CodeSet_Utf8FormDToUtf8FormC((const char *)dent->d_name, length,
+                                           &entryName, &entryNameLen)) {
+            LOG(4, ("%s: Unable to normalize form C \"%s\"\n", __FUNCTION__,
                     dent->d_name));
             /* Skip this entry and continue. */
             free(dent);
@@ -4098,24 +4174,25 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
           * share gets resolved into its full path, and gets its attributes
           * via HgfsGetattrFromName.
           */
+
          if (strcmp(dent->d_name, ".") == 0 ||
              strcmp(dent->d_name, "..") == 0) {
-            LOG(4, ("HgfsServerSearchRead: assigning %s default "
-                    "attributes\n", dent->d_name));
+            LOG(4, ("%s: assigning %s default attributes\n",
+                    __FUNCTION__, dent->d_name));
             HgfsServerGetDefaultDirAttrs(&attr);
          } else {
             /* Check permission on the share and get the share path */
             nameStatus =
-               HgfsServerPolicy_GetSharePath(dent->d_name,
-                                             length,
+               HgfsServerPolicy_GetSharePath(dent->d_name, length,
                                              HGFS_OPEN_MODE_READ_ONLY,
                                              &sharePathLen,
                                              (char const **)&sharePath);
             if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-               LOG(4, ("HgfsServerSearchRead: No such share or access denied\n"));
+               LOG(4, ("%s: No such share or access denied\n", __FUNCTION__));
                free(dent);
                free(search.utf8Dir);
                free(search.utf8ShareName);
+
                return HgfsConvertFromNameStatus(nameStatus);
             }
 
@@ -4125,13 +4202,15 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
              * problems on the host, the server still enumerates it and
              * returns to the client.
              */
+
             status = HgfsGetattrFromName(sharePath, configOptions, dent->d_name,
                                         &attr, NULL);
             if (status != 0) {
                /*
                 * The dent no longer exists. Log the event.
                 */
-               LOG(4, ("HgfsServerSearchRead: stat FAILED\n"));
+
+               LOG(4, ("%s: stat FAILED\n", __FUNCTION__));
             }
          }
 
@@ -4139,6 +4218,7 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
          * No conversion needed on OS X because dent->d_name is the shareName
          * that was converted to normal form C in hgfsServerPolicyHost.
          */
+
         entryName = dent->d_name;
         entryNameLen = length;
          break;
@@ -4148,6 +4228,7 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
           * The POSIX implementation of HgfsSearchOpen could not have created
           * this kind of search.
           */
+
          NOT_IMPLEMENTED();
          break;
       default:
@@ -4157,13 +4238,14 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
 
       free(search.utf8Dir);
       free(search.utf8ShareName);
-      LOG(4, ("HgfsServerSearchRead: dent name is \"%s\" len = %"FMTSZ"u\n",
+      LOG(4, ("%s: dent name is \"%s\" len = %"FMTSZ"u\n", __FUNCTION__,
               entryName, entryNameLen));
 
       /*
        * We need to unescape the name before sending it back to the client
        */
-      HgfsEscape_Undo(entryName, entryNameLen + 1);
+
+      entryNameLen = HgfsEscape_Undo(entryName, entryNameLen + 1);
 
       /*
        * XXX: HgfsPackSearchReadReply will error out if the dent we
@@ -4172,9 +4254,10 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
        * one with success. Now we return an error. This may be a non-issue
        * since what filesystems allow dent lengths as high as 6144 bytes?
        */
+
       status = 0;
-      if (!HgfsPackSearchReadReply(packetIn, status, entryName, entryNameLen, &attr,
-                                   &packetOut, &packetOutSize)) {
+      if (!HgfsPackSearchReadReply(packetIn, status, entryName, entryNameLen,
+                                   &attr, &packetOut, &packetOutSize)) {
          status = EPROTO;
       }
 
@@ -4193,7 +4276,7 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
    /* No entry at this offset */
    free(search.utf8Dir);
    free(search.utf8ShareName);
-   LOG(4, ("HgfsServerSearchRead: no entry\n"));
+   LOG(4, ("%s: no entry\n", __FUNCTION__));
    status = 0;
    if (!HgfsPackSearchReadReply(packetIn, status, NULL, 0, &attr,
                                 &packetOut, &packetOutSize)) {
@@ -4203,6 +4286,7 @@ HgfsServerSearchRead(char const *packetIn,     // IN: incoming packet
        !HgfsPacketSend(packetOut, packetOutSize, session, 0)) {
       free(packetOut);
    }
+
    return status;
 }
 
@@ -4247,14 +4331,8 @@ HgfsServerGetattr(char const *packetIn,     // IN: incoming packet
    ASSERT(packetIn);
    ASSERT(session);
 
-   if (!HgfsUnpackGetattrRequest(packetIn,
-                                 packetSize,
-                                 &attr,
-                                 &hints,
-                                 &cpName,
-                                 &cpNameSize,
-                                 &file,
-                                &caseFlags)) {
+   if (!HgfsUnpackGetattrRequest(packetIn, packetSize, &attr, &hints, &cpName,
+                                 &cpNameSize, &file, &caseFlags)) {
       status = EPROTO;
       goto exit;
    }
@@ -4265,7 +4343,7 @@ HgfsServerGetattr(char const *packetIn,     // IN: incoming packet
       status = HgfsGetFd(file, session, FALSE, &fd);
 
       if (status != 0) {
-         LOG(4, ("HgfsServerGetattr: Could not get file descriptor\n"));
+         LOG(4, ("%s: Could not get file descriptor\n", __FUNCTION__));
          goto exit;
       }
       status = HgfsGetattrFromFd(fd, session, &attr);
@@ -4276,12 +4354,10 @@ HgfsServerGetattr(char const *packetIn,     // IN: incoming packet
        * Depending on whether this file/dir is real or virtual, either
        * forge its attributes or look them up in the actual filesystem.
        */
-      nameStatus = HgfsServerGetAccess(cpName,
-                                       cpNameSize,
+
+      nameStatus = HgfsServerGetAccess(cpName, cpNameSize,
                                        HGFS_OPEN_MODE_READ_ONLY,
-                                       caseFlags,
-                                       &localName,
-                                       NULL);
+                                       caseFlags, &localName, NULL);
 
       switch (nameStatus) {
       case HGFS_NAME_STATUS_INCOMPLETE_BASE:
@@ -4289,7 +4365,8 @@ HgfsServerGetattr(char const *packetIn,     // IN: incoming packet
           * This is the base of our namespace; make up fake status for
           * this directory.
           */
-         LOG(4, ("HgfsServerGetattr: getting attrs for base dir\n"));
+
+         LOG(4, ("%s: getting attrs for base dir\n", __FUNCTION__));
          HgfsServerGetDefaultDirAttrs(&attr);
          break;
 
@@ -4301,7 +4378,7 @@ HgfsServerGetattr(char const *packetIn,     // IN: incoming packet
          nameStatus = HgfsServerPolicy_GetShareOptions(cpName, cpNameSize,
                                                        &configOptions);
          if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-            LOG(4, ("HgfsServerGetattr: no matching share: %s.\n", cpName));
+            LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, cpName));
             free(localName);
             status = ENOENT;
             goto exit;
@@ -4380,14 +4457,8 @@ HgfsServerSetattr(char const *packetIn,     // IN: incoming packet
    ASSERT(packetIn);
    ASSERT(session);
 
-   if (!HgfsUnpackSetattrRequest(packetIn,
-                                 packetSize,
-                                 &attr,
-                                 &hints,
-                                 &cpName,
-                                 &cpNameSize,
-                                 &file,
-                                &caseFlags)) {
+   if (!HgfsUnpackSetattrRequest(packetIn, packetSize, &attr, &hints,
+                                 &cpName, &cpNameSize, &file, &caseFlags)) {
       status = EPROTO;
       goto exit;
    }
@@ -4395,12 +4466,8 @@ HgfsServerSetattr(char const *packetIn,     // IN: incoming packet
    if (file != HGFS_INVALID_HANDLE) {
       status = HgfsSetattrFromFd(file, session, &attr, hints);
    } else {
-      status = HgfsSetattrFromName(cpName,
-                                   cpNameSize,
-                                   &attr,
-                                   hints,
-                                  caseFlags,
-                                   session);
+      status = HgfsSetattrFromName(cpName, cpNameSize, &attr, hints,
+                                  caseFlags, session);
    }
    if (!HgfsPackSetattrReply(packetIn, status, &packetOut, &packetOutSize)) {
       status = EPROTO;
@@ -4456,14 +4523,12 @@ HgfsServerCreateDir(char const *packetIn,     // IN: incoming packet
       return EPROTO;
    }
 
-   nameStatus = HgfsServerGetAccess(info.cpName,
-                                    info.cpNameSize,
+   nameStatus = HgfsServerGetAccess(info.cpName, info.cpNameSize,
                                     HGFS_OPEN_MODE_WRITE_ONLY,
-                                    info.caseFlags,
-                                    &localName,
-                                    NULL);
+                                    info.caseFlags, &localName, NULL);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsServerCreateDir: access check failed\n"));
+      LOG(4, ("%s: access check failed\n", __FUNCTION__));
+
       return HgfsConvertFromNameStatus(nameStatus);
    }
 
@@ -4479,6 +4544,7 @@ HgfsServerCreateDir(char const *packetIn,     // IN: incoming packet
     * a directory requires a valid mode, it's highly unlikely that we'll ever
     * be creating a directory without owner permissions.
     */
+
    permissions = ~ALLPERMS;
    permissions |= info.mask & HGFS_CREATE_DIR_VALID_SPECIAL_PERMS ?
                   info.specialPerms << 9 : 0;
@@ -4489,7 +4555,7 @@ HgfsServerCreateDir(char const *packetIn,     // IN: incoming packet
    permissions |= info.mask & HGFS_CREATE_DIR_VALID_OTHER_PERMS ?
                   info.otherPerms : (permissions & S_IRWXU) >> 6;
 
-   LOG(4, ("HgfsServerCreateDir: making dir \"%s\", mode %"FMTMODE"\n",
+   LOG(4, ("%s: making dir \"%s\", mode %"FMTMODE"\n", __FUNCTION__,
            localName, permissions));
 
    error = Posix_Mkdir(localName, permissions);
@@ -4499,13 +4565,14 @@ HgfsServerCreateDir(char const *packetIn,     // IN: incoming packet
        *  Set hidden attribute when requested.
        *  Do not fail directory creation if setting hidden attribute fails.
        */
+
       HgfsSetHiddenXAttr(localName, TRUE);
    }
 
    free(localName);
    if (error) {
       error = errno;
-      LOG(4, ("HgfsServerCreateDir: error: %s\n", strerror(error)));
+      LOG(4, ("%s: error: %s\n", __FUNCTION__, strerror(error)));
       return error;
    }
    if (!HgfsPackCreateDirReply(packetIn, 0, &packetOut, &packetOutSize)) {
@@ -4557,45 +4624,40 @@ HgfsServerDeleteFile(char const *packetIn,     // IN: incoming packet
    ASSERT(packetIn);
    ASSERT(session);
 
-   if (!HgfsUnpackDeleteRequest(packetIn,
-                                packetSize,
-                                &cpName,
-                                &cpNameSize,
-                                &hints,
-                                &file,
-                               &caseFlags)) {
+   if (!HgfsUnpackDeleteRequest(packetIn, packetSize, &cpName, &cpNameSize,
+                                &hints, &file, &caseFlags)) {
       return EPROTO;
    }
 
    if (hints & HGFS_DELETE_HINT_USE_FILE_DESC) {
       if (!HgfsHandle2FileName(file, session, &cpName, &cpNameSize)) {
-         LOG(4, ("HgfsServerDeleteFile: could not map cached file handle %u\n",
+         LOG(4, ("%s: could not map cached file handle %u\n", __FUNCTION__,
                  file));
+
          return EBADF;
       }
       localName = cpName;
 
    } else {
-      nameStatus = HgfsServerGetAccess(cpName,
-                                       cpNameSize,
-                                       HGFS_OPEN_MODE_WRITE_ONLY,
-                                       caseFlags,
-                                       &localName,
-                                       NULL);
+      nameStatus = HgfsServerGetAccess(cpName, cpNameSize,
+                                       HGFS_OPEN_MODE_WRITE_ONLY, caseFlags,
+                                       &localName, NULL);
       if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-         LOG(4, ("HgfsServerDeleteFile: access check failed\n"));
+         LOG(4, ("%s: access check failed\n", __FUNCTION__));
+
          return HgfsConvertFromNameStatus(nameStatus);
       }
    }
 
    ASSERT(localName);
 
-   LOG(4, ("HgfsServerDeleteFile: unlinking \"%s\"\n", localName));
+   LOG(4, ("%s: unlinking \"%s\"\n", __FUNCTION__, localName));
    error = Posix_Unlink(localName);
    free(localName);
    if (error) {
       error = errno;
-      LOG(4, ("HgfsServerDeleteFile: error: %s\n", strerror(error)));
+      LOG(4, ("%s: error: %s\n", __FUNCTION__, strerror(error)));
+
       return error;
    }
    if (!HgfsPackDeleteReply(packetIn, 0, &packetOut, &packetOutSize)) {
@@ -4647,51 +4709,47 @@ HgfsServerDeleteDir(char const *packetIn,     // IN: incoming packet
    ASSERT(packetIn);
    ASSERT(session);
 
-   if (!HgfsUnpackDeleteRequest(packetIn,
-                                packetSize,
-                                &cpName,
-                                &cpNameSize,
-                                &hints,
-                                &file,
-                               &caseFlags)) {
+   if (!HgfsUnpackDeleteRequest(packetIn, packetSize, &cpName, &cpNameSize,
+                                &hints, &file, &caseFlags)) {
       return EPROTO;
    }
 
    if (hints & HGFS_DELETE_HINT_USE_FILE_DESC) {
       if (!HgfsHandle2FileName(file, session, &cpName, &cpNameSize)) {
-         LOG(4, ("HgfsServerDeleteDir: could not map cached file handle %u\n",
+         LOG(4, ("%s: could not map cached file handle %u\n", __FUNCTION__,
             file));
+
          return EBADF;
       }
       localName = cpName;
 
    } else {
-      nameStatus = HgfsServerGetAccess(cpName,
-                                       cpNameSize,
+      nameStatus = HgfsServerGetAccess(cpName, cpNameSize,
                                        HGFS_OPEN_MODE_WRITE_ONLY,
-                                       caseFlags,
-                                       &localName,
-                                       NULL);
+                                       caseFlags, &localName, NULL);
       if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-         LOG(4, ("HgfsServerDeleteDir: access check failed\n"));
+         LOG(4, ("%s: access check failed\n", __FUNCTION__));
+
          return HgfsConvertFromNameStatus(nameStatus);
       }
    }
 
    /* Guest OS is not allowed to delete shared folder. */
    if (HgfsServerIsSharedFolderOnly(cpName, cpNameSize)){
-      LOG(4, ("HgfsServerDeleteDir: Cannot delete shared folder\n"));
+      LOG(4, ("%s: Cannot delete shared folder\n", __FUNCTION__));
+
       return EPERM;
    }
 
    ASSERT(localName);
 
-   LOG(4, ("HgfsServerDeleteDir: removing \"%s\"\n", localName));
+   LOG(4, ("%s: removing \"%s\"\n", __FUNCTION__, localName));
    error = Posix_Rmdir(localName);
    free(localName);
    if (error) {
       error = errno;
-      LOG(4, ("HgfsServerDeleteDir: error: %s\n", strerror(error)));
+      LOG(4, ("%s: error: %s\n", __FUNCTION__, strerror(error)));
+
       return error;
    }
 
@@ -4701,6 +4759,7 @@ HgfsServerDeleteDir(char const *packetIn,     // IN: incoming packet
    if (!HgfsPacketSend(packetOut, packetOutSize, session, 0)) {
       free(packetOut);
    }
+
    return 0;
 }
 
@@ -4751,56 +4810,47 @@ HgfsServerRename(char const *packetIn,     // IN: incoming packet
    ASSERT(packetIn);
    ASSERT(session);
 
-   if (!HgfsUnpackRenameRequest(packetIn,
-                                packetSize,
-                                &cpOldName,
-                                &cpOldNameLen,
-                                &cpNewName,
-                                &cpNewNameLen,
-                                &hints,
-                                &srcFile,
-                                &targetFile,
-                               &oldCaseFlags,
-                               &newCaseFlags)) {
+   if (!HgfsUnpackRenameRequest(packetIn, packetSize, &cpOldName, &cpOldNameLen,
+                                &cpNewName, &cpNewNameLen, &hints, &srcFile,
+                                &targetFile, &oldCaseFlags, &newCaseFlags)) {
       return EPROTO;
    }
 
    if (hints & HGFS_RENAME_HINT_USE_SRCFILE_DESC) {
       size_t localOldNameLen;
 
-      if (!HgfsHandle2FileName(srcFile, session, &localOldName, &localOldNameLen)) {
-         LOG(4, ("HgfsServerDeleteFile: could not map cached source file handle %u\n",
-                 srcFile));
+      if (!HgfsHandle2FileName(srcFile, session, &localOldName,
+                               &localOldNameLen)) {
+         LOG(4, ("%s: could not map cached source file handle %u\n",
+                 __FUNCTION__, srcFile));
+
          return EBADF;
       }
 
       /* Guest OS is not allowed to rename shared folder. */
       if (HgfsHandleIsSharedFolderOpen(srcFile, session, &sharedFolderOpen) &&
           sharedFolderOpen) {
-         LOG(4, ("HgfsServerRename: Cannot rename shared folder\n"));
+         LOG(4, ("%s: Cannot rename shared folder\n", __FUNCTION__));
          status = EPERM;
          goto exit;
       }
 
    } else {
 
-      nameStatus = HgfsServerGetAccess(cpOldName,
-                                       cpOldNameLen,
+      nameStatus = HgfsServerGetAccess(cpOldName, cpOldNameLen,
                                        HGFS_OPEN_MODE_READ_WRITE,
-                                       oldCaseFlags,
-                                       &localOldName,
-                                       NULL);
+                                       oldCaseFlags, &localOldName, NULL);
       if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-         LOG(4, ("HgfsServerRename: old name access check failed\n"));
+         LOG(4, ("%s: old name access check failed\n", __FUNCTION__));
+
          return HgfsConvertFromNameStatus(nameStatus);
       }
 
       ASSERT(localOldName);
 
       /* Guest OS is not allowed to rename shared folder. */
-      if (HgfsServerIsSharedFolderOnly(cpOldName,
-                                       cpOldNameLen)){
-         LOG(4, ("HgfsServerRename: Cannot rename shared folder\n"));
+      if (HgfsServerIsSharedFolderOnly(cpOldName, cpOldNameLen)) {
+         LOG(4, ("%s: Cannot rename shared folder\n", __FUNCTION__));
          status = EPERM;
          goto exit;
       }
@@ -4809,30 +4859,29 @@ HgfsServerRename(char const *packetIn,     // IN: incoming packet
    if (hints & HGFS_RENAME_HINT_USE_TARGETFILE_DESC) {
       size_t localNewNameLen;
 
-      if (!HgfsHandle2FileName(targetFile, session, &localNewName, &localNewNameLen)) {
-         LOG(4, ("HgfsServerDeleteFile: could not map cached target file handle %u\n",
-                 targetFile));
+      if (!HgfsHandle2FileName(targetFile, session, &localNewName,
+                               &localNewNameLen)) {
+         LOG(4, ("%s: could not map cached target file handle %u\n",
+                 __FUNCTION__, targetFile));
+
          return EBADF;
       }
 
       /* Guest OS is not allowed to rename shared folder. */
       if (HgfsHandleIsSharedFolderOpen(targetFile, session, &sharedFolderOpen) &&
           sharedFolderOpen) {
-         LOG(4, ("HgfsServerRename: Cannot rename shared folder\n"));
+         LOG(4, ("%s: Cannot rename shared folder\n", __FUNCTION__));
          status = EPERM;
          goto exit;
       }
 
    } else {
 
-      nameStatus = HgfsServerGetAccess(cpNewName,
-                                       cpNewNameLen,
+      nameStatus = HgfsServerGetAccess(cpNewName, cpNewNameLen,
                                        HGFS_OPEN_MODE_WRITE_ONLY,
-                                       newCaseFlags,
-                                       &localNewName,
-                                       NULL);
+                                       newCaseFlags, &localNewName, NULL);
       if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-         LOG(4, ("HgfsServerRename: new name access check failed\n"));
+         LOG(4, ("%s: new name access check failed\n", __FUNCTION__));
          status = HgfsConvertFromNameStatus(nameStatus);
          goto exit;
       }
@@ -4848,7 +4897,7 @@ HgfsServerRename(char const *packetIn,     // IN: incoming packet
       nameStatus = HgfsServerPolicy_GetShareOptions(cpNewName, cpNewNameLen,
                                                     &configOptions);
       if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-         LOG(4, ("HgfsServerRename: no matching share: %s.\n", cpNewName));
+         LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, cpNewName));
          status = ENOENT;
          goto exit;
       }
@@ -4857,22 +4906,23 @@ HgfsServerRename(char const *packetIn,     // IN: incoming packet
        * We were asked to avoid replacing an existing file,
        * so fail if the target exists.
        */
+
       status = HgfsGetattrFromName(localNewName, configOptions, cpNewName,
                                    &attr, NULL);
       if (status == 0) {
          /* The target exists, and so must fail the rename. */
-         LOG(4, ("HgfsServerRename: error: target %s exists\n", localNewName));
+         LOG(4, ("%s: error: target %s exists\n", __FUNCTION__, localNewName));
          status = EEXIST;
          goto exit;
       }
    }
 
-   LOG(4, ("HgfsServerRename: renaming \"%s\" to \"%s\"\n",
+   LOG(4, ("%s: renaming \"%s\" to \"%s\"\n", __FUNCTION__,
            localOldName, localNewName));
    error = Posix_Rename(localOldName, localNewName);
    if (error) {
       error = errno;
-      LOG(4, ("HgfsServerRename: error: %s\n", strerror(error)));
+      LOG(4, ("%s: error: %s\n", __FUNCTION__, strerror(error)));
       status = error;
       goto exit;
    }
@@ -4883,6 +4933,7 @@ HgfsServerRename(char const *packetIn,     // IN: incoming packet
     * XXX: Note that this operation can fail (out of memory), but we'd like
     * the client to see success anyway, because the rename succeeded.
     */
+
    status = 0;
    HgfsUpdateNodeNames(localOldName, localNewName, session);
    if (!HgfsPackRenameReply(packetIn, status, &packetOut, &packetOutSize)) {
@@ -4973,8 +5024,9 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
        * We don't yet support file handle for this operation.
        * Clients should retry using the file name.
        */
+
       if (requestV3->fileName.flags & HGFS_FILE_NAME_USE_FILE_DESC) {
-         LOG(4, ("HgfsServerQueryVolume: Doesn't support file handle.\n"));
+         LOG(4, ("%s: Doesn't support file handle.\n", __FUNCTION__));
          status = EPARAMETERNOTSUPPORTED;
         goto exit;
       }
@@ -4990,7 +5042,7 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
       caseFlags = requestV3->fileName.caseType;
       fileName = requestV3->fileName.name;
       fileNameLength = requestV3->fileName.length;
-      LOG(4, ("HgfsServerQueryVolume: HGFS_OP_QUERY_VOLUME_INFO_V3\n"));
+      LOG(4, ("%s: HGFS_OP_QUERY_VOLUME_INFO_V3\n", __FUNCTION__));
    } else {
       HgfsRequestQueryVolume *request = (HgfsRequestQueryVolume *)packetIn;
       HgfsReplyQueryVolume *reply;
@@ -5014,6 +5066,7 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
     * request->fileName.length is user-provided, so this test must be carefully
     * written to prevent wraparounds.
     */
+
    if (fileNameLength > extra) {
       /* The input packet is smaller than the request. */
       status = EPROTO;
@@ -5021,12 +5074,9 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
    }
 
    /* It is now safe to read the file name field. */
-   nameStatus = HgfsServerGetAccess(fileName,
-                                    fileNameLength,
+   nameStatus = HgfsServerGetAccess(fileName, fileNameLength,
                                     HGFS_OPEN_MODE_READ_WRITE,
-                                    caseFlags,
-                                    &utf8Name,
-                                    &utf8NameLen);
+                                    caseFlags, &utf8Name, &utf8NameLen);
    switch (nameStatus) {
    case HGFS_NAME_STATUS_INCOMPLETE_BASE:
       /*
@@ -5034,7 +5084,8 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
        * QueryVolumeInfo on it, on individual shares, or on just about
        * any pathname.
        */
-      LOG(4,("HgfsServerQueryVolume: opened search on base\n"));
+
+      LOG(4,("%s: opened search on base\n", __FUNCTION__));
       status = HgfsServerSearchVirtualDir(HgfsServerPolicy_GetShares,
                                           HgfsServerPolicy_GetSharesInit,
                                           HgfsServerPolicy_GetSharesCleanup,
@@ -5065,8 +5116,10 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
        * Now go through all shares and get share paths on the server.
        * Then retrieve space info for each share's volume.
        */
+
       offset = 0;
-      while ((dent = HgfsGetSearchResult(handle, session, offset, TRUE)) != NULL) {
+      while ((dent = HgfsGetSearchResult(handle, session, offset,
+                                         TRUE)) != NULL) {
          char const *sharePath;
          size_t sharePathLen;
          uint64 freeBytes  = 0;
@@ -5080,8 +5133,9 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
           * need to make sure to handle them properly. In particular, they
           * should be ignored within QueryVolume, as they're not real shares.
           */
+
          if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {
-            LOG(4, ("HgfsServerQueryVolume: Skipping fake share %s\n",
+            LOG(4, ("%s: Skipping fake share %s\n", __FUNCTION__, 
                     dent->d_name));
             free(dent);
             continue;
@@ -5091,6 +5145,7 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
           * The above check ignores '.' and '..' so we do not include them in
           * the share count here.
           */
+
          shares++;
 
          /*
@@ -5100,15 +5155,14 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
           * then do we check if there were any failures; if all shares failed
           * to process then we bail out with an error code.
           */
-         nameStatus = HgfsServerPolicy_GetSharePath(dent->d_name,
-                                                    length,
+
+         nameStatus = HgfsServerPolicy_GetSharePath(dent->d_name, length,
                                                     HGFS_OPEN_MODE_READ_ONLY,
                                                     &sharePathLen,
                                                     &sharePath);
          free(dent);
          if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-            LOG(4, ("HgfsServerQueryVolume: No such share or access "
-                    "denied\n"));
+            LOG(4, ("%s: No such share or access denied\n", __FUNCTION__));
             if (0 == firstErr) {
                firstErr = HgfsConvertFromNameStatus(nameStatus);
             }
@@ -5118,8 +5172,8 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
 
          if (!HgfsServerStatFs(sharePath, sharePathLen,
                                &freeBytes, &totalBytes)) {
-            LOG(4, ("HgfsServerQueryVolume: error getting volume "
-                    "information\n"));
+            LOG(4, ("%s: error getting volume information\n",
+                    __FUNCTION__));
             if (0 == firstErr) {
                firstErr = EIO;
             }
@@ -5131,6 +5185,7 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
           * Pick the drive with amount of space available and return that
           * according to different volume info type.
           */
+
          switch (infoType) {
          case VOLUME_INFO_TYPE_MIN:
             if ((outFreeBytes > freeBytes) || firstShare) {
@@ -5150,23 +5205,23 @@ HgfsServerQueryVolume(char const *packetIn,     // IN: incoming packet
          }
       }
       if (!HgfsRemoveSearch(handle, session)) {
-         LOG(4, ("HgfsServerQueryVolume: could not close search on base\n"));
+         LOG(4, ("%s: could not close search on base\n", __FUNCTION__));
       }
       break;
    case HGFS_NAME_STATUS_COMPLETE:
       ASSERT(utf8Name);
-      LOG(4,("HgfsServerQueryVolume: querying path %s\n", utf8Name));
+      LOG(4,("%s: querying path %s\n", __FUNCTION__, utf8Name));
       success = HgfsServerStatFs(utf8Name, utf8NameLen,
                                  &outFreeBytes, &outTotalBytes);
       free(utf8Name);
       if (!success) {
-         LOG(4, ("HgfsServerQueryVolume: error getting volume information\n"));
+         LOG(4, ("%s: error getting volume information\n", __FUNCTION__));
          status = EIO;
          goto exit;
       }
       break;
    default:
-      LOG(4,("HgfsServerQueryVolume: file access check failed\n"));
+      LOG(4,("%s: file access check failed\n", __FUNCTION__));
       status = HgfsConvertFromNameStatus(nameStatus);
       goto exit;
    }
@@ -5234,7 +5289,7 @@ HgfsServerSymlinkCreate(char const *packetIn,     // IN: incoming packet
       HgfsReplySymlinkCreateV3 *replyV3;
       HgfsFileNameV3 *targetNameP;
       requestV3 = (HgfsRequestSymlinkCreateV3 *)HGFS_REQ_GET_PAYLOAD_V3(packetIn);
-      LOG(4, ("HgfsServerSymlinkCreate: HGFS_OP_CREATE_SYMLINK_V3\n"));
+      LOG(4, ("%s: HGFS_OP_CREATE_SYMLINK_V3\n", __FUNCTION__));
 
       /* Enforced by the dispatch function. */
       ASSERT(packetSize >= HGFS_REQ_PAYLOAD_SIZE_V3(requestV3));
@@ -5248,6 +5303,7 @@ HgfsServerSymlinkCreate(char const *packetIn,     // IN: incoming packet
        * targetName starts after symlinkName + the variable length array
        * in symlinkName.
        */
+
       targetNameP = (HgfsFileNameV3 *)(symlinkName + 1 + symlinkNameLength);
       targetName = targetNameP->name;
       targetNameLength = targetNameP->length;
@@ -5256,61 +5312,65 @@ HgfsServerSymlinkCreate(char const *packetIn,     // IN: incoming packet
        * We don't yet support file handle for this operation.
        * Clients should retry using the file name.
        */
+
       if (requestV3->symlinkName.flags & HGFS_FILE_NAME_USE_FILE_DESC ||
           targetNameP->flags & HGFS_FILE_NAME_USE_FILE_DESC) {
-         LOG(4, ("HgfsServerSymlinkCreate: Doesn't support file handle.\n"));
-         return EPARAMETERNOTSUPPORTED;
-      }
-
-      packetOutSize = HGFS_REP_PAYLOAD_SIZE_V3(replyV3);
-      packetOut = Util_SafeMalloc(packetOutSize);
-      replyV3 = (HgfsReplySymlinkCreateV3 *)HGFS_REP_GET_PAYLOAD_V3(packetOut);
-      replyV3->reserved = 0;
-   } else {
-      HgfsRequestSymlinkCreate *request;
-      HgfsFileName *targetNameP;
-      request = (HgfsRequestSymlinkCreate *)packetIn;
-
-      /* Enforced by the dispatch function. */
-      ASSERT(packetSize >= sizeof *request);
-      extra = packetSize - sizeof *request;
-
-      symlinkName = request->symlinkName.name;
-      symlinkNameLength = request->symlinkName.length;
-
-      /*
-       * targetName starts after symlinkName + the variable length array
-       * in symlinkName.
-       */
-      targetNameP = (HgfsFileName *)(symlinkName + 1 + symlinkNameLength);
-      targetName = targetNameP->name;
-      targetNameLength = targetNameP->length;
-      packetOutSize = sizeof(struct HgfsReplySymlinkCreate);
-      packetOut = Util_SafeMalloc(packetOutSize);
-   }
-
-   /*
-    * request->symlinkName.length is user-provided, so this test must
-    * be carefully written to prevent wraparounds.
-    */
-   if (symlinkNameLength > extra) {
-      /* The input packet is smaller than the request */
-      status = EPROTO;
-      goto exit;
-   }
-   /*
-    * It is now safe to read the symlink file name and the
-    * "targetName" field
-    */
-
-   nameStatus = HgfsServerGetAccess(symlinkName,
-                                    symlinkNameLength,
-                                    HGFS_OPEN_MODE_READ_WRITE,
-                                    caseFlags,
-                                    &localSymlinkName,
-                                    NULL);
-   if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsServerSymlinkCreate: symlink name access check failed\n"));
+                LOG(4, ("%s: Doesn't support file handle.\n", __FUNCTION__));
+
+                return EPARAMETERNOTSUPPORTED;
+             }
+
+             packetOutSize = HGFS_REP_PAYLOAD_SIZE_V3(replyV3);
+             packetOut = Util_SafeMalloc(packetOutSize);
+             replyV3 = (HgfsReplySymlinkCreateV3 *)HGFS_REP_GET_PAYLOAD_V3(packetOut);
+             replyV3->reserved = 0;
+          } else {
+             HgfsRequestSymlinkCreate *request;
+             HgfsFileName *targetNameP;
+             request = (HgfsRequestSymlinkCreate *)packetIn;
+
+             /* Enforced by the dispatch function. */
+             ASSERT(packetSize >= sizeof *request);
+             extra = packetSize - sizeof *request;
+
+             symlinkName = request->symlinkName.name;
+             symlinkNameLength = request->symlinkName.length;
+
+             /*
+              * targetName starts after symlinkName + the variable length array
+              * in symlinkName.
+              */
+
+             targetNameP = (HgfsFileName *)(symlinkName + 1 + symlinkNameLength);
+             targetName = targetNameP->name;
+             targetNameLength = targetNameP->length;
+             packetOutSize = sizeof(struct HgfsReplySymlinkCreate);
+             packetOut = Util_SafeMalloc(packetOutSize);
+          }
+
+          /*
+           * request->symlinkName.length is user-provided, so this test must
+           * be carefully written to prevent wraparounds.
+           */
+
+          if (symlinkNameLength > extra) {
+             /* The input packet is smaller than the request */
+             status = EPROTO;
+             goto exit;
+          }
+
+          /*
+           * It is now safe to read the symlink file name and the
+           * "targetName" field
+           */
+
+          nameStatus = HgfsServerGetAccess(symlinkName, symlinkNameLength,
+                                           HGFS_OPEN_MODE_READ_WRITE,
+                                           caseFlags, &localSymlinkName,
+                                           NULL);
+          if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
+             LOG(4, ("%s: symlink name access check failed\n",
+                      __FUNCTION__));
       status = HgfsConvertFromNameStatus(nameStatus);
       goto exit;
    }
@@ -5322,6 +5382,7 @@ HgfsServerSymlinkCreate(char const *packetIn,     // IN: incoming packet
     * targetNameLength is user-provided, so this test must be carefully
     * written to prevent wraparounds.
     */
+
    if (targetNameLength > extra) {
       /* The input packet is smaller than the request */
       free(localSymlinkName);
@@ -5335,7 +5396,7 @@ HgfsServerSymlinkCreate(char const *packetIn,     // IN: incoming packet
    nameStatus = HgfsServerPolicy_GetShareOptions(symlinkName, symlinkNameLength,
                                                  &configOptions);
    if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
-      LOG(4, ("HgfsServerSymlinkCreate: no matching share: %s.\n", symlinkName));
+      LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, symlinkName));
       status = HgfsConvertFromNameStatus(nameStatus);
       goto exit;
    }
@@ -5346,12 +5407,13 @@ HgfsServerSymlinkCreate(char const *packetIn,     // IN: incoming packet
    localTargetName[targetNameLength] = '\0';
 
    /* Prohibit symlink ceation if symlink following is enabled. */
-   if (HgfsServerPolicy_IsShareOptionSet(configOptions, HGFS_SHARE_FOLLOW_SYMLINKS)) {
+   if (HgfsServerPolicy_IsShareOptionSet(configOptions,
+                                         HGFS_SHARE_FOLLOW_SYMLINKS)) {
       status = EPERM;
       goto exit;
    }
 
-   LOG(4, ("HgfsServerSymlinkCreate: creating \"%s\" linked to \"%s\"\n",
+   LOG(4, ("%s: creating \"%s\" linked to \"%s\"\n", __FUNCTION__,
            localSymlinkName, localTargetName));
 
    /* XXX: Should make use of targetNameP->flags? */
@@ -5359,7 +5421,7 @@ HgfsServerSymlinkCreate(char const *packetIn,     // IN: incoming packet
    free(localSymlinkName);
    if (error) {
       status = errno;
-      LOG(4, ("HgfsServerSymlinkCreate: error: %s\n", strerror(errno)));
+      LOG(4, ("%s: error: %s\n", __FUNCTION__, strerror(errno)));
       goto exit;
    }
 
@@ -5368,10 +5430,12 @@ HgfsServerSymlinkCreate(char const *packetIn,     // IN: incoming packet
                               session, 0)) {
       goto exit;
    }
+
    return status;
 
 exit:
    free(packetOut);
+
    return status;
 }
 
@@ -5435,7 +5499,9 @@ HgfsServerHasSymlink(const char *fileName,        // IN
    ASSERT(sharePath);
    ASSERT(sharePathLength <= fileNameLength);
 
-   LOG(4, ("%s: fileName: %s, sharePath: %s#\n", __FUNCTION__, fileName, sharePath));
+   LOG(4, ("%s: fileName: %s, sharePath: %s#\n", __FUNCTION__,
+           fileName, sharePath));
+
    /*
     * Return success if:
     * - empty fileName or
@@ -5443,6 +5509,7 @@ HgfsServerHasSymlink(const char *fileName,        // IN
     *   access to entire host) or
     * - fileName and sharePath are same.
     */
+
    if (fileNameLength == 0 ||
        sharePathLength == 0 ||
        Str_Strcmp(sharePath, fileName) == 0) {
@@ -5451,21 +5518,24 @@ HgfsServerHasSymlink(const char *fileName,      // IN
 
    /* Separate out parent directory of the fileName. */
    File_GetPathName(fileName, &fileDirName, NULL);
+
    /*
-    * File_GetPathName may return an empty string to signify the root of the filesystem.
-    * To simplify subsequent processing, let's convert such empty strings to "/" when
-    * found. See File_GetPathName header comment for details.
+    * File_GetPathName may return an empty string to signify the root of
+    * the filesystem. To simplify subsequent processing, let's convert such
+    * empty strings to "/" when found. See File_GetPathName header comment
+    * for details.
     */
+
    if (strlen(fileDirName) == 0) {
       char *p;
-      p = realloc(fileDirName, sizeof(DIRSEPS));
+      p = realloc(fileDirName, sizeof (DIRSEPS));
       if (p == NULL) {
          nameStatus = HGFS_NAME_STATUS_OUT_OF_MEMORY;
          LOG(4, ("%s: failed to realloc fileDirName.\n", __FUNCTION__));
          goto exit;
       } else {
          fileDirName = p;
-         Str_Strcpy(fileDirName, DIRSEPS, sizeof(DIRSEPS));
+         Str_Strcpy(fileDirName, DIRSEPS, sizeof (DIRSEPS));
       }
    }
 
@@ -5473,6 +5543,7 @@ HgfsServerHasSymlink(const char *fileName,        // IN
     * Resolve parent directory of fileName.
     * Use realpath(2) to resolve the parent.
     */
+
    resolvedFileDirPath = Posix_RealPath(fileDirName);
    if (resolvedFileDirPath == NULL) {
       /* Let's return some meaningful errors if possible. */
@@ -5504,6 +5575,7 @@ HgfsServerHasSymlink(const char *fileName,        // IN
 exit:
    free(resolvedFileDirPath);
    free(fileDirName);
+
    return nameStatus;
 }
 
@@ -5566,13 +5638,14 @@ HgfsAckOplockBreak(ServerLockData *lockData, // IN: server lock info
 
    ASSERT(lockData);
    fileDesc = lockData->fileDesc;
-   LOG(4, ("HgfsAckOplockBreak: Acknowledging break on fd %d\n", fileDesc));
+   LOG(4, ("%s: Acknowledging break on fd %d\n", __FUNCTION__, fileDesc));
 
    /*
     * The Linux server supports lock downgrading. We only downgrade to a shared
     * lock if our previous call to fcntl() said we could, and if the client
     * wants to downgrade to a shared lock. Otherwise, we break altogether.
     */
+
    if (lockData->serverLock == HGFS_LOCK_SHARED &&
        replyLock == HGFS_LOCK_SHARED) {
       newLock = F_RDLCK;
@@ -5585,8 +5658,8 @@ HgfsAckOplockBreak(ServerLockData *lockData, // IN: server lock info
    /* Downgrade or acknowledge the break altogether. */
    if (fcntl(fileDesc, F_SETLEASE, newLock) == -1) {
       int error = errno;
-      Log("HgfsServer_AckServerOplockBreak: Could not break lease on fd %d: "
-          "%s\n", fileDesc, strerror(error));
+      Log("%s: Could not break lease on fd %d: %s\n",
+          __FUNCTION__, fileDesc, strerror(error));
    }
 
    /* Cleanup. */
@@ -5676,12 +5749,14 @@ HgfsGetHiddenXAttr(char const *fileName,   // IN: File name
          break;
       }
       default:
-         LOG(4, ("HgfsGetHiddenXattr: Unrecognized object type %d\n", attrBuf.objType));
+         LOG(4, ("%s: Unrecognized object type %d\n", __FUNCTION__,
+                 attrBuf.objType));
          err = EINVAL;
       }
    } else {
-      LOG(4, ("HgfsGetHiddenXattr: Error %d when getting attributes\n", err));
+      LOG(4, ("%s: Error %d when getting attributes\n", __FUNCTION__, err));
    }
+
    return err;
 }
 
@@ -5691,8 +5766,8 @@ HgfsGetHiddenXAttr(char const *fileName,   // IN: File name
  *
  * ChangeInvisibleFlag --
  *
- *    Changes value of the invisible bit in a flags variable to a value defined by
- *    setFlag parameter.
+ *    Changes value of the invisible bit in a flags variable to a value defined
+ *    by setFlag parameter.
  *
  * Results:
  *    TRUE flag has been changed, FALSE otherwise.
@@ -5772,7 +5847,8 @@ HgfsSetHiddenXAttr(char const *fileName,       // IN: path to the file
          break;
       }
       default:
-         LOG(4, ("HgfsGetHiddenXattr: Unrecognized object type %d\n", attrBuf.objType));
+         LOG(4, ("%s: Unrecognized object type %d\n", __FUNCTION__,
+                 attrBuf.objType));
          err = EINVAL;
       }
    } else {
index e84e237ebcda498c305ab112d32c17827609cb2a..9a67e824b1843f1c2780e581650825ee09f0b546 100644 (file)
@@ -298,12 +298,7 @@ ImageUtil_ConstructPNGBuffer(const ImageInfo *image, // IN
                              DynBuf *imageData)      // OUT
 
 {
-   ImagePngWriteOptions options;
-
-   options.zlibCompressLevel = -1;
-   options.stripAlphaChannel = TRUE;
-
-   return ImageUtil_ConstructPNGBufferEx(image, &options, imageData);
+   return ImageUtil_ConstructPNGBufferEx(image, NULL, imageData);
 }
 
 
@@ -326,9 +321,9 @@ ImageUtil_ConstructPNGBuffer(const ImageInfo *image, // IN
  */
 
 Bool
-ImageUtil_ConstructPNGBufferEx(const ImageInfo *image,              // IN
-                               const ImagePngWriteOptions *options, // IN
-                               DynBuf *imageData)                   // OUT
+ImageUtil_ConstructPNGBufferEx(const ImageInfo *image,               // IN
+                               const ImagePngWriteOptions *pOptions, // IN/OPT
+                               DynBuf *imageData)                    // OUT
 {
    png_structp png_ptr;
    png_infop info_ptr;
@@ -344,15 +339,22 @@ ImageUtil_ConstructPNGBufferEx(const ImageInfo *image,              // IN
 
    int bytes_per_line;
    png_bytep *row_pointers;
+   ImagePngWriteOptions options;
 
    ASSERT(image);
    ASSERT(imageData);
-   ASSERT(options);
 
-   if (!image || !options || !imageData) {
+   if (!image || !imageData) {
       return FALSE;
    }
 
+   if (pOptions == NULL) {
+      options.zlibCompressLevel = -1;
+      options.stripAlphaChannel = TRUE;
+   } else {
+      options = *pOptions;
+   }
+
    row_pointers = malloc(sizeof *row_pointers * image->height);
    if (!row_pointers) {
       return FALSE;
@@ -400,8 +402,8 @@ ImageUtil_ConstructPNGBufferEx(const ImageInfo *image,              // IN
    png_set_IHDR(png_ptr, info_ptr, image->width, image->height, 8, color_type,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
 
-   if (options->zlibCompressLevel >= 0 && options->zlibCompressLevel <= 9) {
-      png_set_compression_level(png_ptr, options->zlibCompressLevel);
+   if (options.zlibCompressLevel >= 0 && options.zlibCompressLevel <= 9) {
+      png_set_compression_level(png_ptr, options.zlibCompressLevel);
    }
 
 #ifdef RGB_MASK
@@ -463,7 +465,7 @@ ImageUtil_ConstructPNGBufferEx(const ImageInfo *image,              // IN
 
       png_set_PLTE(png_ptr, info_ptr, palette, image->numColors);
    } else if (image->bpp == 32) {
-      if (options->stripAlphaChannel) {
+      if (options.stripAlphaChannel) {
 
          /*
           * Strip the alpha channel
@@ -493,7 +495,7 @@ ImageUtil_ConstructPNGBufferEx(const ImageInfo *image,              // IN
    /* Write the file header information.  REQUIRED */
    png_write_info(png_ptr, info_ptr);
 
-   if ((image->bpp == 32) && options->stripAlphaChannel) {
+   if ((image->bpp == 32) && options.stripAlphaChannel) {
       /* treat the alpha channel byte as filler */
       png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
    }
index 5671ab22733a32dea97b310232fe0ea0bc592b08..0595eae1e5df760ee5b97bca457e55928c49ff9d 100644 (file)
 #ifndef _APP_UTIL_H_
 #define _APP_UTIL_H_
 
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
 #include "vmware.h"
 #include "guestCaps.h"
 
+#ifdef __cplusplus
+};
+#endif // __cplusplus
+
 
 #ifdef _WIN32
 
+/* The maximum number of icons that can be retrieved in a single query. */
+#define APPUTIL_MAX_NUM_ICONS 16
+
+/* Predefined (N x N pixels) icon sizes */
+#define APPUTIL_ICON_SMALL 16
+#define APPUTIL_ICON_BIG 32
+
+
 typedef struct _AppUtilIconEntry {
    uint32 width;
    uint32 height;
@@ -49,6 +66,10 @@ typedef enum {
    APPUTIL_LOWER_LEFT_DIB = 1,     // the origin is the lower-left corner of the bitmap
 } AppUtilBitmapOrigin;
 
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
 Bool AppUtil_GetIconDataByHandle(HICON hIcon,
                                  AppUtilBitmapOrigin origin,
                                  AppUtilIconEntry *icon);
@@ -66,6 +87,23 @@ HICON AppUtil_GetWindowIcon(HWND hwnd,
 
 void AppUtil_BuildGlobalApplicationList(void);
 char *AppUtil_ActionURIForCommandLine(const WCHAR *commandLineUtf16);
+Bool AppUtil_GetLinkIconData(const TCHAR *path,
+                             AppUtilIconInfo *iconInfo,
+                             AppUtilBitmapOrigin dibOrientation);
+Bool AppUtil_GetAppIconData(HWND hwnd,
+                            const TCHAR *path,
+                            AppUtilIconInfo *iconInfo,
+                            AppUtilBitmapOrigin dibOrientation);
+
+Bool
+AppUtil_GetIconIndexAndLocationForShortcut(const TCHAR *shortcut,
+                                           int maxLen,
+                                           TCHAR *iconFile,
+                                           int *iconIndex);
+
+#ifdef __cplusplus
+};
+#endif // __cplusplus
 
 #endif //_WIN32
 
index d1da1e96c3f7b3a896afe8e5d20da0f7d9a849d8..8500c6adfa2af9b90be0744ddc9a471702f65127 100644 (file)
@@ -1,12 +1,12 @@
 #define BUILD_NUMBER \
-       "build-172495"
+       "build-179896"
 #define BUILD_NUMBER_NUMERIC \
-       172495
+       179896
 #define BUILD_NUMBER_NUMERIC_STRING \
-       "172495"
+       "179896"
 #define PRODUCT_BUILD_NUMBER \
-       "product-build-584"
+       "product-build-620"
 #define PRODUCT_BUILD_NUMBER_NUMERIC \
-       584
+       620
 #define PRODUCT_BUILD_NUMBER_NUMERIC_STRING \
-       "584"
+       "620"
index 5f16c77830f3a2445902fe671b1b0f19b9cb823e..5f44fd9cc9258997c555edb182567bdecb12bf4f 100644 (file)
@@ -75,7 +75,7 @@ typedef struct ListItem {
 /*
  * delete item from the list
  */
-#define   LIST_DEL            DelListItem   
+#define   LIST_DEL            DelListItem
 
 /*
  * link two lists together
@@ -100,7 +100,7 @@ typedef struct ListItem {
 /*
  * Get the list size.
  */
-#define   LIST_SIZE          GetListSize
+#define   LIST_SIZE           GetListSize
 
 /*
  * LIST_SCAN_FROM scans the list from "from" up until "until".
@@ -113,7 +113,7 @@ typedef struct ListItem {
    for (p = (from); (p) != NULL;   \
       (p) = (((p)->member == (until)) ? NULL : (p)->member))
 
-/* scan the entire list (non-destructively) */ 
+/* scan the entire list (non-destructively) */
 #define   LIST_SCAN(p, l)   \
    LIST_SCAN_FROM(p, LIST_FIRST(l), LIST_FIRST(l), next)
 
@@ -145,7 +145,7 @@ typedef struct ListItem {
  *      Returns the next member of a doubly linked list, or NULL if last.
  *      Assumes: p is member of the list headed by head.
  *
- * Result
+ * Result:
  *      If head or p is NULL, return NULL. Otherwise,
  *      next list member (or null if last).
  *
@@ -176,7 +176,7 @@ NextListItem(ListItem *p,        // IN
  *      Returns the prev member of a doubly linked list, or NULL if first.
  *      Assumes: p is member of the list headed by head.
  *
- * Result
+ * Result:
  *      If head or prev is NULL, return NULL. Otherwise,
  *      prev list member (or null if first).
  *
@@ -207,7 +207,7 @@ PrevListItem(ListItem *p,        // IN
  *      list header itself.
  *      Assumes neither p nor headp is null and p is a member of *headp.
  *
- * Result
+ * Result:
  *      None
  *
  * Side effects:
@@ -246,7 +246,7 @@ DelListItem(ListItem *p,         // IN
  *      Adds a new member to the back of a doubly linked list (queue)
  *      Assumes neither p nor headp is null and p is not a member of *headp.
  *
- * Result
+ * Result:
  *      None
  *
  * Side effects:
@@ -272,7 +272,7 @@ QueueListItem(ListItem *p,              // IN
       head->prev = p;
    }
 }
-                                                                                
+
 
 /*
  *----------------------------------------------------------------------
@@ -282,7 +282,7 @@ QueueListItem(ListItem *p,              // IN
  *      Adds a new member to the front of a doubly linked list (stack)
  *      Assumes neither p nor headp is null and p is not a member of *headp.
  *
- * Result
+ * Result:
  *      None
  *
  * Side effects:
@@ -298,7 +298,7 @@ PushListItem(ListItem *p,               // IN
    QueueListItem(p, headp);
    *headp = p;
 }
+
 
 /*
  *----------------------------------------------------------------------
@@ -310,7 +310,7 @@ PushListItem(ListItem *p,               // IN
  *      No checking is done. It is assumed that l1 and l2 are two
  *      distinct lists.
  *
- * Result
+ * Result:
  *      A list { l1 l2 }.
  *
  * Side effects:
@@ -357,11 +357,11 @@ SpliceLists(ListItem *l1,      // IN
  *      Make a list l = {l1 l2} into two separate lists {l1} and {l2}, where:
  *      l = { ... x -> p -> ... } split into:
  *      l1 = { ... -> x }
- *      l2 = { p -> ... } 
+ *      l2 = { p -> ... }
  *      Assumes neither p nor l is null and p is a member of l.
  *      If p is the first element of l, then l1 will be NULL.
  *
- * Result
+ * Result:
  *      None.
  *
  * Side effects:
@@ -414,7 +414,7 @@ SplitLists(ListItem *p,         // IN
  */
 
 static INLINE int
-GetListSize(ListItem *head)    // IN
+GetListSize(ListItem *head)     // IN
 {
    ListItem *li;
    int ret = 0;
index e34bd57b532c03a60b16bd4ac83aa4689c1778bd..9ae5bc615e90bb95ca2f04b599993966649aa9ac 100644 (file)
@@ -81,6 +81,7 @@ EXTERN int32 Config_GetTriState(int32 defaultValue,
 EXTERN double Config_GetDouble(double defaultValue,
                                const char *fmt, ...) PRINTF_DECL(2, 3);
 EXTERN Bool Config_NotSet(const char *fmt, ...) PRINTF_DECL(1, 2);
+EXTERN void Config_Unset(const char *fmt, ...) PRINTF_DECL(1, 2);
 EXTERN void Config_UnsetWithPrefix(const char *fmt, ...) PRINTF_DECL(1, 2);
 
 EXTERN void Config_Set(void *value, int type,
index 9a21a57ccbf183964f2f5a9ff2170adb225fec2b..4c23be0dea18309a01a5b7d34e35d24827e276b8 100644 (file)
 #ifndef _DBLLNKLST_H_
 #define _DBLLNKLST_H_
 
-#include "vm_basic_types.h"
-
 #define INCLUDE_ALLOW_MODULE
 #define INCLUDE_ALLOW_USERLEVEL
 #include "includeCheck.h"
 
+#include "vm_basic_types.h"
+
 
 #define DblLnkLst_OffsetOf(type, field) ((intptr_t)&((type *)0)->field)
 
 #define DblLnkLst_Container(addr, type, field) \
-   ((type *)((char *)addr - DblLnkLst_OffsetOf(type, field)))
+   ((type *)((char *)(addr) - DblLnkLst_OffsetOf(type, field)))
 
 #define DblLnkLst_ForEach(curr, head)                   \
       for (curr = (head)->next; curr != (head); curr = (curr)->next)
@@ -94,18 +94,199 @@ typedef struct DblLnkLst_Links {
 } DblLnkLst_Links;
 
 
-/* Functions for both circular and anchored lists. --hpreg */
+/*
+ * Functions
+ *
+ * DblLnkLst_LinkFirst and DblLnkLst_LinkLast are specific
+ * to anchored lists.  The rest are for both circular and
+ * anchored lists.
+ */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Init --
+ *
+ *    Initialize a member of a doubly linked list
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Init(DblLnkLst_Links *l) // IN
+{
+   l->prev = l->next = l;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Link --
+ *
+ *    Merge two doubly linked lists into one
+ *
+ *    The operation is commutative
+ *    The operation is inversible (its inverse is DblLnkLst_Unlink)
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Link(DblLnkLst_Links *l1, // IN
+               DblLnkLst_Links *l2) // IN
+{
+   DblLnkLst_Links *tmp;
+
+   (tmp      = l1->prev)->next = l2;
+   (l1->prev = l2->prev)->next = l1;
+    l2->prev = tmp                 ;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Unlink --
+ *
+ *    Split one doubly linked list into two
+ *
+ *    No check is performed: the caller must ensure that both members
+ *    belong to the same doubly linked list
+ *
+ *    The operation is commutative
+ *    The operation is inversible (its inverse is DblLnkLst_Link)
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
 
-void DblLnkLst_Init(DblLnkLst_Links *l);
-void DblLnkLst_Link(DblLnkLst_Links *l1, DblLnkLst_Links *l2);
-void DblLnkLst_Unlink(DblLnkLst_Links *l1, DblLnkLst_Links *l2);
-void DblLnkLst_Unlink1(DblLnkLst_Links *l);
-Bool DblLnkLst_IsLinked(DblLnkLst_Links const *l);
+static INLINE void
+DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN
+                 DblLnkLst_Links *l2) // IN
+{
+   DblLnkLst_Links *tmp;
 
-/* Functions specific to anchored lists. --hpreg */
+   tmp       = l1->prev            ;
+   (l1->prev = l2->prev)->next = l1;
+   (l2->prev = tmp     )->next = l2;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Unlink1 --
+ *
+ *    Unlink an element from its list.
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Unlink1(DblLnkLst_Links *l) // IN
+{
+   DblLnkLst_Unlink(l, l->next);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * DblLnkLst_IsLinked --
+ *
+ *    Determines whether an element is linked with any other elements.
+ *
+ * Results:
+ *    TRUE if link is linked, FALSE otherwise.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+DblLnkLst_IsLinked(DblLnkLst_Links const *l) // IN
+{
+   /*
+    * A DblLnkLst_Links is either linked to itself (not linked) or linked to
+    * other elements in a list (linked).
+    */
+   return l->prev != l;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_LinkFirst --
+ *
+ *    Insert 'l' at the beginning of the list anchored at 'head'
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN
+                    DblLnkLst_Links *l)    // IN
+{
+   DblLnkLst_Link(head->next, l);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_LinkLast --
+ *
+ *    Insert 'l' at the end of the list anchored at 'head'
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
 
-void DblLnkLst_LinkFirst(DblLnkLst_Links *head, DblLnkLst_Links *l);
-void DblLnkLst_LinkLast(DblLnkLst_Links *head, DblLnkLst_Links *l);
+static INLINE void
+DblLnkLst_LinkLast(DblLnkLst_Links *head, // IN
+                   DblLnkLst_Links *l)    // IN
+{
+   DblLnkLst_Link(head, l);
+}
 
 
 #endif /* _DBLLNKLST_H_ */
index 6693a3a62087c1c2da0b5e0af4237e0a15f62774..61ae90565736105f555789788a174f55e12dc56b 100644 (file)
@@ -65,12 +65,14 @@ class LIB_EXPORT DnDBase
       /* Local UI as DnD target. */
       sigc::signal<void, DND_DROPEFFECT> updateFeedbackChanged;
       sigc::signal<void, bool, int, int> updateDetWndChanged;
-      sigc::signal<void, bool, uint32> updateUnityDetWndChanged;
+      sigc::signal<void, bool, uint32, bool> updateUnityDetWndChanged;
+      sigc::signal<void, int32, int32> targetPrivateDropChanged;
 
       sigc::signal<void> reset;
       sigc::signal<void> disable;
       sigc::signal<void> enable;
       sigc::signal<void, int, int> updateMouseChanged;
+      sigc::signal<void> moveDetWndToMousePos;
 
       /* Guest cancel signals. */
       sigc::signal<void> ghCancel;
index 1a8e9ae7c008be843b28a204aff793515bc3a46c..17998016f887d12184565fd8c8e322c3350f3a46 100644 (file)
@@ -89,6 +89,9 @@ typedef enum {
    DND_UPDATE_HOST_VERSION,
    DND_UPDATE_GUEST_VERSION,
    DND_UPDATE_MOUSE,
+   DND_GH_PRIVATE_DROP,
+   DND_GH_TRANSPORT_TEST,
+   DND_MOVE_DET_WND_TO_MOUSE_POS,
    DND_MAX,
 } DnDCommand;
 
@@ -112,6 +115,7 @@ typedef enum {
    CP_HG_START_FILE_COPY,
 
    // Add future commands here.
+   CP_GH_TRANSPORT_TEST,
    CP_MAX,
 } CopyPasteCommand;
 
index cb4a7d8e7e25beeb099ce44fdff232dc4b3f07b0..63dbcd729ffefdd2e71227a80bb6ec0e97681e75 100644 (file)
@@ -47,6 +47,15 @@ Escape_Undo(char escByte,      // IN
             size_t sizeIn,     // IN
             size_t *sizeOut);  // OUT
 
+const char *
+Escape_Strchr(char escByte,      // IN
+              const char *bufIn, // IN
+              char c);           // IN
+
+char *
+Escape_Unescape(char escByte,       // IN
+                const char *bufIn); // IN
+
 void *
 Escape_AnsiToUnix(void const *bufIn, // IN
                   size_t sizeIn,     // IN
index 90ce9a647d0fe19fc424d3a55e2b05420ed089cb..5b89098ca7c252ad8d13d14de8c148b12d92b5af 100644 (file)
@@ -186,11 +186,22 @@ EXTERN Bool File_SetTimes(ConstUnicode pathName,
                           VmTimeType writeTime,
                           VmTimeType attrChangeTime);
 
+EXTERN Bool File_GetFilePermissions(ConstUnicode pathName,
+                                   int *mode);
+
+EXTERN Bool File_SetFilePermissions(ConstUnicode pathName,
+                                    int mode);
+
 EXTERN Bool File_SupportsFileSize(ConstUnicode pathName,
                                   uint64 fileSize);
 
 EXTERN Bool File_SupportsLargeFiles(ConstUnicode pathName);
 
+EXTERN char *File_MapPathPrefix(const char *oldPath,
+                                const char **oldPrefixes,
+                                const char **newPrefixes,
+                                size_t numPrefixes);
+
 EXTERN Bool File_CopyFromFdToFd(FileIODescriptor src, 
                                 FileIODescriptor dst);
 
@@ -286,6 +297,8 @@ EXTERN Bool File_MakeCfgFileExecutable(ConstUnicode pathName);
 
 EXTERN char *File_ExpandAndCheckDir(const char *dirName);
 
+EXTERN Bool File_SupportsPrealloc(const char *file);
+
 #ifdef __cplusplus
 } // extern "C" {
 #endif
index abc5af8c70f668e2a8d4d1e28ee7ea09d9a188a9..608624c0fe05d9deb85b355b43adb71761d5e391 100644 (file)
@@ -62,7 +62,10 @@ typedef enum {
    GHI_CAP_TRASH_FOLDER                 = 17, // supports ghi.guest.trashFolder.action,
                                               // ghi.guest.trashFolder.state, and
                                               // ghi.guest.trashFolder.getIcon commands
-   CAP_SET_TOPO_MODES                   = 18  // supports setting topology modes in video driver
+   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
+   GHI_CAP_GET_EXEC_INFO_HASH           = 21, // supports ghi.guest.getExecInfoHash
 } GuestCapabilities;
 
 typedef struct {
@@ -122,7 +125,10 @@ static GuestCapElem guestCapTable[] = {
    { UNITY_CAP_STATUS_UNITY_ACTIVE,        UNITY_CAP_VMDB_PATH, "unityActive" },
    { GHI_CAP_SET_OUTLOOK_TEMP_FOLDER,      GHI_CAP_VMDB_PATH,   "setOutlookTempFolder" },
    { GHI_CAP_TRASH_FOLDER,                 GHI_CAP_VMDB_PATH,   "trashFolder" },
-   { CAP_SET_TOPO_MODES,                   CAP_VMDB_PATH, "displayTopologyModesSet" }
+   { 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"},
+   { GHI_CAP_GET_EXEC_INFO_HASH,           GHI_CAP_VMDB_PATH,   "getExecInfoHash"},
 };
 
 #endif // VM_NEED_VMDB_GUEST_CAP_MAPPING
index 98d1b52e8c8204888a2b031b9aab168dd5edefbd..9601edc36e15e8da405bbebd834f5081bb38db24 100644 (file)
@@ -117,18 +117,30 @@ typedef enum GuestOSFamilyType {
 #define ALLWINNET64    BS(WINNET_64)
 #define ALLWINNET      (ALLWINNET32 | ALLWINNET64)
 
-#define ALLWINVISTA32   (BS(LONGHORN) | BS(WINVISTA))
-#define ALLWINVISTA64   (BS(LONGHORN_64) | BS(WINVISTA_64))
+#define ALLWINLONGHORN32  BS(LONGHORN)
+#define ALLWINLONGHORN64  BS(LONGHORN_64)
+#define ALLWINLONGHORN  (ALLWINLONGHORN32 | ALLWINLONGHORN64)
+
+#define ALLWINVISTA32   BS(WINVISTA)
+#define ALLWINVISTA64   BS(WINVISTA_64)
 #define ALLWINVISTA     (ALLWINVISTA32 | ALLWINVISTA64)
 
+#define ALLWIN2008R2_32 BS(WIN2008R2)
+#define ALLWIN2008R2_64 BS(WIN2008R2_64)
+#define ALLWIN2008R2    (ALLWIN2008R2_32 | ALLWIN2008R2_64)
+
 #define ALLWINSEVEN32   BS(WINSEVEN)
 #define ALLWINSEVEN64   BS(WINSEVEN_64)
 #define ALLWINSEVEN     (ALLWINSEVEN32 | ALLWINSEVEN64)
 
 #define ALLWINNT32     (BS(WINNT) | ALLWIN2000 | ALLWINXP32 | ALLWINNET32 | \
-                         ALLWINVISTA32 | ALLWINSEVEN32)
-#define ALLWINNT64     (ALLWINXP64 | ALLWINNET64 | ALLWINVISTA64 | \
-                         ALLWINSEVEN64)
+                         ALLWINVISTA32 | ALLWINLONGHORN32 | \
+                         ALLWINSEVEN32 | ALLWIN2008R2_32)
+
+#define ALLWINNT64     (ALLWINXP64 | ALLWINNET64 | \
+                         ALLWINVISTA64 | ALLWINLONGHORN64 | \
+                         ALLWINSEVEN64 | ALLWIN2008R2_64)
+
 #define ALLWINNT       (ALLWINNT32 | ALLWINNT64)
 
 #define ALLWIN32       (ALLWIN9X | ALLWINNT32)
@@ -141,10 +153,12 @@ typedef enum GuestOSFamilyType {
 #define ALL26XLINUX64   (BS(OTHER26XLINUX_64) | BS(DEBIAN45_64))
 #define ALLLINUX32      (BS(OTHER24XLINUX) | BS(VMKERNEL) | \
                          BS(OTHERLINUX) | ALL26XLINUX32)
-#define ALLLINUX64      (BS(OTHERLINUX_64) | BS(OTHER24XLINUX_64) | ALL26XLINUX64)
+#define ALLLINUX64      (BS(OTHERLINUX_64) | BS(OTHER24XLINUX_64) | \
+                         ALL26XLINUX64)
 #define ALLLINUX        (ALLLINUX32 | ALLLINUX64)
 #define ALLDARWIN32     (BS(DARWIN9) | BS(DARWIN10))
 #define ALLDARWIN64     (BS(DARWIN9_64) | BS(DARWIN10_64))
+#define ALLDARWIN10     (BS(DARWIN10) | BS(DARWIN10_64))
 #define ALLDARWIN       (ALLDARWIN32 | ALLDARWIN64)
 #define ALL64           (ALLWIN64 | ALLLINUX64 | \
                          BS(SOLARIS10_64) | BS(FREEBSD_64) | \
@@ -160,12 +174,16 @@ typedef enum GuestOSFamilyType {
 #define STR_OS_ANNVIX "Annvix" 
 #define STR_OS_ARCH "Arch" 
 #define STR_OS_ARKLINUX "Arklinux" 
+#define STR_OS_ASIANUX_3                "asianux3"
+#define STR_OS_ASIANUX_4                "asianux4"
 #define STR_OS_AUROX "Aurox" 
 #define STR_OS_ASIANUX "asianux" 
 #define STR_OS_BLACKCAT "BlackCat" 
 #define STR_OS_COBALT "Cobalt" 
 #define STR_OS_CONECTIVA "Conectiva" 
-#define STR_OS_DEBIAN "Debian" 
+#define STR_OS_DEBIAN                   "Debian"
+#define STR_OS_DEBIAN_4                 "debian4"
+#define STR_OS_DEBIAN_5                 "debian5"
 #define STR_OS_FEDORA "Fedora" 
 #define STR_OS_GENTOO "Gentoo" 
 #define STR_OS_IMMUNIX "Immunix" 
@@ -256,7 +274,6 @@ typedef enum GuestOSFamilyType {
 #define STR_OS_WIN_NET_DC_FULL "Windows Server 2003 Datacenter Edition"
 #define STR_OS_WIN_NET_DC "winNetDatacenter"
 #define STR_OS_WIN_LONG "longhorn"
-#define STR_OS_WIN_LONG_FULL "Longhorn (experimental)"
 #define STR_OS_WIN_VISTA "winVista"
 #define STR_OS_WIN_VISTA_FULL "Windows Vista"
 #define STR_OS_WIN_VISTA_X64 "winVista-64"
@@ -349,13 +366,15 @@ typedef enum GuestOSFamilyType {
 #define STR_OS_WIN_SEVEN_HOME_BASIC_FULL   "Windows 7 Home Basic"
 #define STR_OS_WIN_SEVEN_HOME_PREMIUM_FULL "Windows 7 Home Premium"
 #define STR_OS_WIN_SEVEN_ULTIMATE_FULL     "Windows 7 Ultimate"
-#define STR_OS_WIN_SEVEN_BUSINESS_FULL     "Windows 7 Business"
+#define STR_OS_WIN_SEVEN_PROFESSIONAL_FULL "Windows 7 Professional"
+#define STR_OS_WIN_SEVEN_ENTERPRISE_FULL   "Windows 7 Enterprise"
 
 /* Windows Server 2008 R2 (based on Windows 7) */
 
 #define STR_OS_WIN_2008R2     "windows7srv"
 #define STR_OS_WIN_2008R2_X64 "windows7srv-64"
 
+#define STR_OS_WIN_2008R2_FOUNDATION_FULL "Windows Server 2008 R2 Foundation Edition"
 #define STR_OS_WIN_2008R2_STANDARD_FULL   "Windows Server 2008 R2 Standard Edition"
 #define STR_OS_WIN_2008R2_ENTERPRISE_FULL "Windows Server 2008 R2 Enterprise Edition"
 #define STR_OS_WIN_2008R2_DATACENTER_FULL "Windows Server 2008 R2 Datacenter Edition"
index e0db2baeb5b96cdac68ae32d5f97791e718da4d2..3828b2c06026357e25da8e86d120cabf761a2618 100644 (file)
@@ -92,6 +92,11 @@ Bool
 HashTable_Delete(HashTable  *hashTable,
                  const char *keyStr);
 
+Bool
+HashTable_LookupAndDelete(HashTable  *hashTable,
+                          const char *keyStr,
+                         void **clientData);
+
 void
 HashTable_Clear(HashTable *ht);
 
index 23e56c4c72f1a14f6c2b105c590f907db3a6716c..3651448e9fd2e3442b737483c74334c0fe04fa61 100644 (file)
@@ -403,6 +403,7 @@ typedef uint64 HgfsAttrFlags;
 #define HGFS_ATTR_SYSTEM      (1 << 1)
 #define HGFS_ATTR_ARCHIVE     (1 << 2)
 #define HGFS_ATTR_HIDDEN_FORCED (1 << 3)
+#define HGFS_ATTR_REPARSE_POINT (1 << 4)
 
 
 /*
index aa20ae1cb179d37fdc68b03045a3b75b65dee3cc..ea140c46de8067ad7e274f3129c81916df1ffd07 100644 (file)
@@ -167,7 +167,9 @@ typedef enum {
    OS_DETAIL_WIN2K3_EN       = 16,
    OS_DETAIL_WIN2K3_BUS      = 17,
    OS_DETAIL_VISTA           = 18,
-   OS_DETAIL_WINSEVEN        = 19,    // Windows 7
+   OS_DETAIL_WIN2K8          = 19,
+   OS_DETAIL_WINSEVEN        = 20,    // Windows 7
+   OS_DETAIL_WIN2K8R2        = 21,
    OS_DETAIL_UNKNOWN         = 99999  // last, highest value
 } OS_DETAIL_TYPE;
 
index 590c6e13be7e3b709e14ab0e0302b1f272891a4b..13e34eaafc7a4d960b30a1ce781d6e3e73753d8f 100644 (file)
@@ -37,6 +37,9 @@
 EXTERN Bool ImageUtil_ReadPNG(ImageInfo *image,
                               ConstUnicode pathName,
                               int pngReadFlags);
+EXTERN Bool ImageUtil_WritePNG(const ImageInfo *image,
+                               ConstUnicode pathName,
+                               const ImagePngWriteOptions *options);
 
 EXTERN Bool ImageUtil_WriteImage(const ImageInfo *image,
                                  ConstUnicode pathName,
@@ -55,11 +58,7 @@ EXTERN Bool ImageUtil_ConstructBuffer(const ImageInfo *image, ImageType imageTyp
                                       DynBuf *imageData);
 EXTERN void ImageUtil_FreeImageData(ImageInfo *image);
 
-EXTERN Bool ImageUtil_CopyImageRect(const ImageInfo *srcImage,
-                                    uint32 x,
-                                    uint32 y,
-                                    uint32 width,
-                                    uint32 height,
-                                    ImageInfo *dstImage);
+EXTERN Bool ImageUtil_Combine(const ImageInfo *images, const VMPoint *origins,
+                              size_t n, ImageInfo *combined);
 
 #endif // _IMAGEUTIL_H_
index aed790f703ec958a19f40f3fb5b3b742f38ee54a..306ad517373f8163af098abbbdc0ff35f03d467a 100644 (file)
@@ -72,7 +72,7 @@ typedef struct {
 } ImageInfo;
 
 typedef struct {
-   int zlibCompressLevel;
+   int zlibCompressLevel; // Set to -1 for the default compression level.
    Bool stripAlphaChannel;
 } ImagePngWriteOptions;
 
index 63a2f2b942d5123ddac8e16e980a68bb632dde71..312b66b9f3bb23e355c0999678279cf099cc150b 100644 (file)
@@ -90,6 +90,7 @@
    LOGLEVEL_VAR(pci_vmxnet3), \
    LOGLEVEL_VAR(vcpuhotplug), \
    LOGLEVEL_VAR(heci), \
+   LOGLEVEL_VAR(vmiopluginlib), \
    \
    /* user/disk */ \
    LOGLEVEL_VAR(aioMgr), \
    LOGLEVEL_VAR(pvfslib), \
    LOGLEVEL_VAR(brtalk), /* macWireless and wpa_supplicant */ \
    LOGLEVEL_VAR(button), \
+   LOGLEVEL_VAR(util), \
    LOGLEVEL_VAR(largepage),
 
 LOGLEVEL_EXTENSION_DECLARE(LOGLEVEL_USER);
index 2095dd0d27322cfbed449237baedffef9676d237..bfb8dc5aadd6c60729c5af139f98e94fb230c39f 100644 (file)
@@ -30,6 +30,8 @@
 #define INCLUDE_ALLOW_VMKERNEL
 #include "includeCheck.h"
 
+#include "vm_basic_defs.h"
+
 #ifndef VMKERNEL
 #include <string.h>
 #endif
index 5cb6a2175ee0035e377e2850ccdf598cde3a61b7..9bf923fba19fdce27fbbffa62b03899199c30210 100644 (file)
@@ -77,4 +77,31 @@ void NetUtil_MonitorIPStart(void);
 void NetUtil_MonitorIPStop(void);
 #endif
 
+#if defined(linux)
+#   ifdef DUMMY_NETUTIL
+/*
+ * Dummy interface table to enable other tools'/libraries' unit tests.
+ */
+typedef struct {
+   int           ifIndex;
+   const char   *ifName;
+} NetUtilIfTableEntry;
+
+
+/*
+ * {-1, NULL}-terminated array of NetUtilIfTableEntry pointers.
+ *
+ * (Test) applications wishing to use the dummy NetUtil_GetIf{Index,Name}
+ * functions must define this variable somewhere.  It allows said apps
+ * to work with a priori knowledge of interface name <=> index mappings
+ * returned by said APIs.
+ */
+EXTERN NetUtilIfTableEntry netUtilIfTable[];
+#   endif // ifdef DUMMY_NETUTIL
+
+int   NetUtil_GetIfIndex(const char *ifName);
+char *NetUtil_GetIfName(int ifIndex);
+
+#endif // if defined(linux)
+
 #endif
index 04f58376c3d2ad747b01e5aadb97871a3c72b236..9ba436fbee3a7610a8163a544959bb4895147a0a 100644 (file)
@@ -74,13 +74,13 @@ Bool Raster_IsModeReasonable(uint32 depth, uint32 bpp, Bool pseudocolor);
 int Raster_GetBPPDepth(uint32 depth, uint32 bpp);
 
 void Raster_ConvertPixels(uint8 *tof, int32 line_increment, int bppdepth,
-                         uint8 *src, int32 src_increment, int src_bppdepth,
-                         Bool pseudoColor, uint32 *pixels,
+                         const uint8 *src, int32 src_increment, int src_bppdepth,
+                         Bool pseudoColor, const uint32 *pixels,
                          uint32 src_x, uint32 src_y,
                          uint32 x, uint32 y, uint32 w, uint32 h);
 
 uint32 Raster_ConvertOnePixel(uint32 pixel, int src_depth, int depth,
-                             Bool pseudoColor, uint32 *pixels);
+                             Bool pseudoColor, const uint32 *pixels);
 
 Bool Raster_ConversionParameters(int depth, uint32 *redMask,
                                 uint32 *greenMask, uint32 *blueMask);
index 3f00239cceaff1b24c4c87f8f4c87a31bf8753d4..cb686e455896241532541730d513e763de54227c 100644 (file)
@@ -91,8 +91,8 @@ SOFTWARE.
 #define NullBox ((BoxPtr)0)
 #define NullRegion ((RegionPtr)0)
 
-#define R_MAXSHORT 32767
-#define R_MINSHORT (-R_MAXSHORT)
+#define R_MAXSHORT SHRT_MAX
+#define R_MINSHORT SHRT_MIN
 
 #define R_MAXINT 0x7FFFFFFF
 #define R_MININT 0x8FFFFFFF
index d3c9790fb6a0f1dcaa3485dd212b17f2b323ac9f..562ae8686447204ff9e1bef06b3825fb9768f308 100644 (file)
 #   define __SYSTEM_H__
 
 #include "vm_basic_types.h"
+#ifdef _WIN32
+#include "dbllnklst.h"
+#endif
 #include "unicode.h"
 
-
 uint64 System_Uptime(void);
 Bool System_GetCurrentTime(int64 *secs, int64 *usecs);
 Bool System_AddToCurrentTime(int64 deltaSecs, int64 deltaUsecs);
 Unicode System_GetTimeAsString(void);
-Bool System_EnableTimeSlew(int64 delta, uint32 timeSyncPeriod);
+Bool System_EnableTimeSlew(int64 delta, int64 timeSyncPeriod);
 Bool System_DisableTimeSlew(void);
 Bool System_IsTimeSlewEnabled(void);
 Bool System_IsACPI(void);
@@ -53,6 +55,18 @@ typedef struct {
    void *cbdata;               // data to pass to callback
 } DesktopSwitchThreadArgs;
 
+/*
+ * Representation of monitors gathered by System_GetMonitors.
+ */
+typedef struct MonListNode {
+   RECT rect;
+   RECT work;
+   BOOL isPrimary;
+   DWORD bpp;
+   BOOL isActive;
+   DblLnkLst_Links l;
+} MonListNode;
+
 /*
  * The value returned by System_GetServiceState if the current state of the
  * vmtools service can't be determined. We need to use a value that is not
@@ -70,6 +84,7 @@ Bool System_StartDesktopSwitchThread(DesktopSwitchThreadArgs *args);
 Bool System_KillDesktopSwitchThread(void);
 Bool System_DisableAndKillScreenSaver(void);
 DWORD System_GetServiceState(LPCWSTR szServiceName);
+DblLnkLst_Links *System_GetMonitors();
 #endif
 
 
index d3f7c801535b589926037faabd80a38f914213b0..fb61dab40eea4fd393416b359892e94fd750fc97 100644 (file)
@@ -24,8 +24,7 @@
  */
 
 /*
- * Breakdown of components involved in Unity (as of change 748058 on
- * 2008/10/23):
+ * Breakdown of components involved in Unity:
  *
  *   1) Unity desktop target
  *
@@ -52,8 +51,7 @@
  *   3) Unity client
  *
  *      This is a VNC-capable client that supports the extensions
- *      specified in VNCEncode_UnitySupported (currently,
- *      VNCUnityWindowRectCap and VNCUnityWindowRegionCap).
+ *      specified in VNCEncode_UnitySupported.
  *
  *      Source: bora/apps/lib/cui/unityMgr.cc
  *              bora/apps/lib/cui/unityMgrVNC.cc
  *
  * -----------------------------------------------------------------------
  *
- * [1] Hosted UI opens VNC connection to VMX (through authd) with
- *     VNCUnityWindowRectCap and VNCUnityWindowRegionCap encodings supported.
+ * [1] Hosted UI opens VNC connection to VMX (through authd) with supported
+ *     encodings of at least what VNCEncode_UnitySupported requires.
  *
  *     MKS remote manager receives VNC connection socket connection
  *     and spins up MKS hostops VNC backend.
 #define GHI_RPC_OUTLOOK_RESTORE_TEMP_FOLDER           "ghi.guest.outlook.restore.tempFolder"
 #define GHI_RPC_TRASH_FOLDER_ACTION                   "ghi.guest.trashFolder.action"
 #define GHI_RPC_TRASH_FOLDER_GET_ICON                 "ghi.guest.trashFolder.getIcon"
+#define GHI_RPC_TRAY_ICON_START_UPDATES               "ghi.guest.trayIcon.startUpdates"
+#define GHI_RPC_TRAY_ICON_STOP_UPDATES                "ghi.guest.trayIcon.stopUpates"
+#define GHI_RPC_TRAY_ICON_SEND_EVENT                  "ghi.guest.trayIcon.sendEvent"
+#define GHI_RPC_SET_FOCUSED_WINDOW                    "ghi.guest.setFocusedWindow"
+#define GHI_RPC_GET_EXEC_INFO_HASH                    "ghi.guest.getExecInfoHash"
 /* @} */
 
 
 #define UNITY_RPC_VMX_SHOW_TASKBAR        "vmx.unity.show.taskbar"
 #define UNITY_RPC_UNITY_CAP               "tools.capability.unity"
 #define UNITY_RPC_SHOW_TASKBAR_CAP        "tools.capability.unity.taskbar"
+#define UNITY_RPC_UNITY_ACTIVE            "unity.active"
 #define GHI_RPC_LAUNCHMENU_CHANGE         "tools.ghi.launchmenu.change"
 #define GHI_RPC_PROTOCOL_HANDLER_INFO     "tools.ghi.protocolhandler.info"
 #define GHI_RPC_TRASH_FOLDER_STATE        "ghi.guest.trashFolder.state"
-#define UNITY_RPC_UNITY_ACTIVE            "unity.active"
-
+#define GHI_RPC_TRAY_ICON_UPDATE          "ghi.guest.trayIcon.update"
 #define GHI_RPC_HOST_SHELL_ACTION         "ghi.host.shell.action"
 /* @} */
 
  * Type definitions
  */
 
+/**
+ * @brief Tray icon event identifiers. See ghiTrayIcon.x.
+ *
+ * @note These identifiers are shared between tools and the VMX. For
+ * compatibility reasons, new events must be added at the end of this
+ * list, and existing event numbers should not be reused if an event
+ * is removed.
+ */
+
+#define GHI_TRAY_ICON_EVENT_INVALID       0
+#define GHI_TRAY_ICON_EVENT_LBUTTONDBLCLK 1
+#define GHI_TRAY_ICON_EVENT_RIGHT_CLICK   2
+#define GHI_TRAY_ICON_EVENT_LEFT_CLICK    3
 
 /**
  * @brief Opaque Unity window identifier.
@@ -343,15 +359,15 @@ typedef enum {
    UNITY_WINDOW_ATTR_MAXIMIZED = 3,         /**< Is maximized.  @note Not mutually exclusive
                                                  with @ref UNITY_WINDOW_STATE_MINIMIZED. */
    UNITY_WINDOW_ATTR_CLOSABLE = 5,          ///< Supports closing.
-   UNITY_WINDOW_ATTR_HAS_TITLEBAR = 6,      ///< @deprecated 
-   UNITY_WINDOW_ATTR_VISIBLE = 7,           ///< @deprecated 
-   UNITY_WINDOW_ATTR_CHILD_WINDOW = 8,      ///< @deprecated 
+   UNITY_WINDOW_ATTR_HAS_TITLEBAR = 6,      ///< @deprecated
+   UNITY_WINDOW_ATTR_VISIBLE = 7,           ///< @deprecated
+   UNITY_WINDOW_ATTR_CHILD_WINDOW = 8,      ///< @deprecated
    UNITY_WINDOW_ATTR_HAS_TASKBAR_BTN = 9,   /**< Should appear in the taskbar.
                                                  @todo Consider deprecation? */
-   UNITY_WINDOW_ATTR_MOVABLE = 10,          ///< Can be moved around the desktop. 
-   UNITY_WINDOW_ATTR_RESIZABLE = 11,        ///< Can be resized. 
-   UNITY_WINDOW_ATTR_ALWAYS_ABOVE = 12,     ///< Should stay on top of stack. 
-   UNITY_WINDOW_ATTR_ALWAYS_BELOW = 13,     ///< Should stay at bottom of stack. 
+   UNITY_WINDOW_ATTR_MOVABLE = 10,          ///< Can be moved around the desktop.
+   UNITY_WINDOW_ATTR_RESIZABLE = 11,        ///< Can be resized.
+   UNITY_WINDOW_ATTR_ALWAYS_ABOVE = 12,     ///< Should stay on top of stack.
+   UNITY_WINDOW_ATTR_ALWAYS_BELOW = 13,     ///< Should stay at bottom of stack.
    UNITY_WINDOW_ATTR_DISABLED = 14,         ///< Keyboard, mouse input is disabled.
    UNITY_WINDOW_ATTR_NOACTIVATE = 15,       /**< Does not raise to foreground via mouse
                                                  click, alt-tab, etc. */
@@ -364,8 +380,8 @@ typedef enum {
    UNITY_WINDOW_ATTR_FULLSCREENABLE = 19,   ///< @deprecated
    UNITY_WINDOW_ATTR_FULLSCREENED = 20,     ///< @deprecated
    UNITY_WINDOW_ATTR_ATTN_WANTED = 21,      ///< Application wants user's attention.
-   UNITY_WINDOW_ATTR_SHADEABLE = 22,        ///< @deprecated 
-   UNITY_WINDOW_ATTR_SHADED = 23,           ///< @deprecated 
+   UNITY_WINDOW_ATTR_SHADEABLE = 22,        ///< @deprecated
+   UNITY_WINDOW_ATTR_SHADED = 23,           ///< @deprecated
    UNITY_WINDOW_ATTR_STICKABLE = 24,        ///< Can be made sticky.
    UNITY_WINDOW_ATTR_STICKY = 25,           ///< Window should appear on all desktops.
    UNITY_WINDOW_ATTR_MODAL = 26,            /**< Modal window.
@@ -413,7 +429,7 @@ typedef uint32 UnityIconSize; // Number of pixels on the larger side of the icon
    @{
 
    @def         UNITY_RPC_ENTER
-   @brief       Tell the guest to go into Unity mode. 
+   @brief       Tell the guest to go into Unity mode.
    @code
    UNITY_RPC_ENTER
    @endcode
@@ -423,11 +439,11 @@ typedef uint32 UnityIconSize; // Number of pixels on the larger side of the icon
 
    @def         UNITY_RPC_GET_UPDATE
    @brief       Get an incremental or full update of window changes detected by
-                the guest. 
+                the guest.
    @todo        Deprecate this RPC in favor of using UNITY_RPC_GET_UPDATE_FULL
                 and UNITY_RPC_GET_UPDATE_INCREMENTAL
    @code
-   UNITY_RPC_GET_UPDATE ["incremental"] 
+   UNITY_RPC_GET_UPDATE ["incremental"]
    @endcode
    @param incremental   If present, do an incremental update, otherwise full.
    @note                A full update reports all current state of all windows,
@@ -455,10 +471,10 @@ execPath ::= ? UTF-8 string uniquely identifying JUST the executable ?
 
 
    @def         UNITY_RPC_GET_BINARY_INFO
-   @brief       Return a list of icons for a window. 
+   @brief       Return a list of icons for a window.
    @todo        Move this into a GHI-specific header.
    @todo        Give this RPC command an intuitive name.
-   @code 
+   @code
    UNITY_RPC_GET_BINARY_INFO windowPath
    @endcode
    @param[in] windowPath UTF-8 encoded "window path" returned by
@@ -473,15 +489,15 @@ execPath ::= ? UTF-8 string uniquely identifying JUST the executable ?
 <nul> := '\0'
 @endverbatim
    @note        Icon data is in BGRA format. An alpha channel value of 255 means
-                "fully opaque", and a value of 0 means "fully transparent". 
+                "fully opaque", and a value of 0 means "fully transparent".
 
 
    @def         UNITY_RPC_GET_BINARY_HANDLERS
    @brief       Ask the guest to return filetypes (extensions) and URL protocols
-                supported by the guest. 
+                supported by the guest.
    @todo        Move this into a GHI-specific header.
-   @code 
-   UNITY_RPC_GET_BINARY_HANDLERS 
+   @code
+   UNITY_RPC_GET_BINARY_HANDLERS
    @endcode
    @sa ghiGetBinaryHandlers.x for format of data returned.
 
@@ -489,10 +505,10 @@ execPath ::= ? UTF-8 string uniquely identifying JUST the executable ?
    @def         UNITY_RPC_OPEN_LAUNCHMENU
    @brief       Get the start menu sub-tree for a given item
    @todo        Move this into a GHI-specific header.
-   @code 
+   @code
    UNITY_RPC_OPEN_LAUNCHMENU root
    @endcode
-   @param[in] root      Name of sub-tree, or "" for root of start menu. 
+   @param[in] root      Name of sub-tree, or "" for root of start menu.
    @return
    <tt>"count handle"</tt>
    \li @c count Number of items in the sub-tree.
@@ -502,7 +518,7 @@ execPath ::= ? UTF-8 string uniquely identifying JUST the executable ?
    @def         UNITY_RPC_GET_LAUNCHMENU_ITEM
    @brief       Get the nth item in the menu sub-tree.
    @todo        Move this into a GHI-specific header.
-   @code 
+   @code
    UNITY_RPC_GET_LAUNCHMENU_ITEM handle index
    @endcode
    @param[in] handle    Handle returned by @ref UNITY_RPC_OPEN_LAUNCHMENU.
@@ -512,44 +528,44 @@ execPath ::= ? UTF-8 string uniquely identifying JUST the executable ?
 
 
    @def         UNITY_RPC_CLOSE_LAUNCHMENU
-   @brief       Close the sub-menu, releasing all associated resources. 
+   @brief       Close the sub-menu, releasing all associated resources.
    @todo        Move this into a GHI-specific header.
-   @code 
+   @code
    UNITY_RPC_CLOSE_LAUNCHMENU handle
    @endcode
    @param[in] handle Handle returned by @ref UNITY_RPC_OPEN_LAUNCHMENU.
 
 
-   @def         UNITY_RPC_WINDOW_SETTOP 
-   @brief       Raise a group of windows to the top of the window stacking order. 
-   @code 
-   UNITY_RPC_WINDOW_SETTOP UnityWindowId{ UnityWindowId} 
+   @def         UNITY_RPC_WINDOW_SETTOP
+   @brief       Raise a group of windows to the top of the window stacking order.
+   @code
+   UNITY_RPC_WINDOW_SETTOP UnityWindowId{ UnityWindowId}
    @endcode
-   @param[in] UnityWindowId{ UnityWindowId} group of windows to raise 
+   @param[in] UnityWindowId{ UnityWindowId} group of windows to raise
    @note        Order of windows is bottom to top.
    @note        Only @ref UNITY_MAX_SETTOP_WINDOW_COUNT windows can be specified.
 
 
-   @def         UNITY_RPC_WINDOW_CLOSE 
-   @brief       Close the specified window. 
-   @code 
-   UNITY_RPC_WINDOW_CLOSE UnityWindowId 
+   @def         UNITY_RPC_WINDOW_CLOSE
+   @brief       Close the specified window.
+   @code
+   UNITY_RPC_WINDOW_CLOSE UnityWindowId
    @endcode
-   @param[in] UnityWindowId window to close 
+   @param[in] UnityWindowId window to close
 
 
    @def         UNITY_RPC_GET_WINDOW_CONTENTS
-   @brief       Retreive pixel contents of the Window. 
-   @code 
-   UNITY_RPC_GET_WINDOW_CONTENTS UnityWindowId 
+   @brief       Retreive pixel contents of the Window.
+   @code
+   UNITY_RPC_GET_WINDOW_CONTENTS UnityWindowId
    @endcode
-   @param[in] UnityWindowId UnityWindowId of window to get contents from 
-   @return      PNG image containing the window content. 
+   @param[in] UnityWindowId UnityWindowId of window to get contents from
+   @return      PNG image containing the window content.
 
 
-   @def         UNITY_RPC_GET_ICON_DATA     
-   @brief       Return icon data for a specific window. 
-   @code 
+   @def         UNITY_RPC_GET_ICON_DATA
+   @brief       Return icon data for a specific window.
+   @code
    UNITY_RPC_GET_ICON_DATA UnityWindowId type size dataOffset dataLength
    @endcode
    @param[in] UnityWindowId     window to get icon data for
@@ -560,55 +576,55 @@ execPath ::= ? UTF-8 string uniquely identifying JUST the executable ?
    @return                      PNG image containing the icon data.
 
 
-   @def         UNITY_RPC_EXIT             
-   @brief       Cease enumerating windows and leave Unity mode. 
-   @code 
-   UNITY_RPC_EXIT 
+   @def         UNITY_RPC_EXIT
+   @brief       Cease enumerating windows and leave Unity mode.
+   @code
+   UNITY_RPC_EXIT
    @endcode
    @note        On success, the guest will send a @ref UNITY_RPC_UNITY_ACTIVE
                 with an argument of 0 to indicate it has exited Unity mode.
 
 
-   @def         UNITY_RPC_GET_UPDATE_FULL  
-   @brief       Equivalent to @ref UNITY_RPC_GET_UPDATE with no argument. 
-   @code 
-   UNITY_RPC_GET_UPDATE_FULL 
+   @def         UNITY_RPC_GET_UPDATE_FULL
+   @brief       Equivalent to @ref UNITY_RPC_GET_UPDATE with no argument.
+   @code
+   UNITY_RPC_GET_UPDATE_FULL
    @endcode
    @return See @ref UnityGetUpdateReturn.
 
 
-   @def         UNITY_RPC_GET_UPDATE_INCREMENTAL 
-   @brief       Equivalent to @ref UNITY_RPC_GET_UPDATE with an "incremental" argument. 
-   @code 
-   UNITY_RPC_GET_UPDATE_INCREMENTAL 
+   @def         UNITY_RPC_GET_UPDATE_INCREMENTAL
+   @brief       Equivalent to @ref UNITY_RPC_GET_UPDATE with an "incremental" argument.
+   @code
+   UNITY_RPC_GET_UPDATE_INCREMENTAL
    @endcode
    @return See @ref UnityGetUpdateReturn.
 
 
-   @def         UNITY_RPC_SHELL_OPEN            
+   @def         UNITY_RPC_SHELL_OPEN
    @brief       Open the application corresponding to the passed in URI or
-                regular path. 
+                regular path.
    @todo        Move this into a GHI-specific header.
-   @code 
-   UNITY_RPC_SHELL_OPEN 
+   @code
+   UNITY_RPC_SHELL_OPEN
    @endcode
-   @param[in] path URI or path of executable to open 
+   @param[in] path URI or path of executable to open
    @note        The URI is opaque to the caller, the caller supplies this URI
                 to the host with the expecation that it will be able to
-                understand the format when this RPC is invoked. 
+                understand the format when this RPC is invoked.
 
 
-   @def         UNITY_RPC_SHOW_TASKBAR         
-   @brief       Show or hide the guest taskbar. 
-   @code 
+   @def         UNITY_RPC_SHOW_TASKBAR
+   @brief       Show or hide the guest taskbar.
+   @code
    UNITY_RPC_SHOW_TASKBAR flag
    @endcode
    @param[in] flag 0 to hide the taskbar, or 1 to show the taskbar.
 
 
-   @def         UNITY_RPC_WINDOW_MOVE_RESIZE  
-   @brief       Change the geometry of the specified window. 
-   @code 
+   @def         UNITY_RPC_WINDOW_MOVE_RESIZE
+   @brief       Change the geometry of the specified window.
+   @code
    UNITY_RPC_WINDOW_MOVE_RESIZE UnityWindowId x y width height
    @endcode
    @param[in] UnityWindowId     UnityWindowId of window to modify
@@ -629,16 +645,16 @@ newHeight ::= ? post-op window height ? ;
 @endverbatim
 
 
-   @def         UNITY_RPC_DESKTOP_WORK_AREA_SET 
-   @brief       Specify the desktop work areas. 
+   @def         UNITY_RPC_DESKTOP_WORK_AREA_SET
+   @brief       Specify the desktop work areas.
    @todo        Add more detail about this RPC and why it matters.
-   @code 
-   UNITY_RPC_DESKTOP_WORK_AREA_SET <work_areas> 
+   @code
+   UNITY_RPC_DESKTOP_WORK_AREA_SET <work_areas>
    @endcode
    @param[in] <work_areas> list of work areas
    @verbatim
-<work_areas> := <count>{ ',' x y width height } 
-<count> := number of work areas to follow, 0 or greater 
+<work_areas> := <count>{ ',' x y width height }
+<count> := number of work areas to follow, 0 or greater
 @endverbatim
 
 
@@ -658,18 +674,18 @@ newHeight ::= ? post-op window height ? ;
    @param[in] UnityWindowId UnityWindowId of window to hide
 
 
-   @def         UNITY_RPC_WINDOW_MINIMIZE    
+   @def         UNITY_RPC_WINDOW_MINIMIZE
    @brief       Minimize the specified window.
-   @code 
+   @code
    UNITY_RPC_WINDOW_MINIMIZE UnityWindowId
    @endcode
-   @param[in] UnityWindowId UnityWindowId of window to minimize 
+   @param[in] UnityWindowId UnityWindowId of window to minimize
 
 
    @def         UNITY_RPC_WINDOW_UNMINIMIZE
    @brief       Unminimizes a window to its pre-minimization state.
-   @code 
-   UNITY_RPC_WINDOW_UNMINIMIZE UnityWindowId 
+   @code
+   UNITY_RPC_WINDOW_UNMINIMIZE UnityWindowId
    @endcode
    @param[in] UnityWindowId window to unminimize
    @note        This RPC originated as UNITY_RPC_WINDOW_RESTORE.  The actual
@@ -677,57 +693,57 @@ newHeight ::= ? post-op window height ? ;
                 backwards compatibility.
 
 
-   @def         UNITY_RPC_WINDOW_MAXIMIZE   
+   @def         UNITY_RPC_WINDOW_MAXIMIZE
    @brief       Maximize the specified window.
-   @code 
+   @code
    UNITY_RPC_WINDOW_MAXIMIZE UnityWindowId
    @endcode
-   @param[in] UnityWindowId UnityWindowId of window to maximize 
+   @param[in] UnityWindowId UnityWindowId of window to maximize
 
 
-   @def         UNITY_RPC_WINDOW_UNMAXIMIZE    
-   @brief       Unmaximize the specified window. 
-   @code 
+   @def         UNITY_RPC_WINDOW_UNMAXIMIZE
+   @brief       Unmaximize the specified window.
+   @code
    UNITY_RPC_WINDOW_UNMAXIMIZE UnityWindowId
    @endcode
-   @param[in] UnityWindowId UnityWindowId of window to unmaximize 
+   @param[in] UnityWindowId UnityWindowId of window to unmaximize
 
 
-   @def         UNITY_RPC_DESKTOP_CONFIG_SET   
-   @brief       Send desktop (virtual workspaces) configuration. 
-   @code 
-   UNITY_RPC_DESKTOP_CONFIG_SET configuration 
+   @def         UNITY_RPC_DESKTOP_CONFIG_SET
+   @brief       Send desktop (virtual workspaces) configuration.
+   @code
+   UNITY_RPC_DESKTOP_CONFIG_SET configuration
    @endcode
-   @param[in] configuration <cell> {<cell>} <current> 
+   @param[in] configuration <cell> {<cell>} <current>
    @verbatim
-<cell> := '{'row,col'}' 
-<current> := currently active cell 
+<cell> := '{'row,col'}'
+<current> := currently active cell
 @endverbatim
-The RPC takes the form of a set of row, column pairs, each enclosed by 
-braces, and an integer. The number of rows and columns can be deduced 
-by looking for the max row and column value specified in these pairs. 
-The integer that follows the list of pairs defines the currently active 
+The RPC takes the form of a set of row, column pairs, each enclosed by
+braces, and an integer. The number of rows and columns can be deduced
+by looking for the max row and column value specified in these pairs.
+The integer that follows the list of pairs defines the currently active
 desktop, as an offset (starting at 0) of the pair list.\n\n
 For example: <tt>{1,1} {1,2} {2,1} {2,2} 1</tt> specifies a 2 x 2 virtual
 desktop where the upper right <tt>{1,2}</tt> is the currently active desktop.
 
 
-   @def         UNITY_RPC_DESKTOP_ACTIVE_SET   
+   @def         UNITY_RPC_DESKTOP_ACTIVE_SET
    @brief       Change the active desktop to the value specified.
-   @code 
+   @code
    UNITY_RPC_DESKTOP_ACTIVE_SET offset
    @endcode
-   @param[in] offset Offset into desktop configuration, as defined by @ref UNITY_RPC_DESKTOP_CONFIG_SET, 0 or greater 
+   @param[in] offset Offset into desktop configuration, as defined by @ref UNITY_RPC_DESKTOP_CONFIG_SET, 0 or greater
 
 
-   @def         UNITY_RPC_WINDOW_DESKTOP_SET   
-   @brief       Change the desktop of the specified window. 
-   @code 
+   @def         UNITY_RPC_WINDOW_DESKTOP_SET
+   @brief       Change the desktop of the specified window.
+   @code
    UNITY_RPC_WINDOW_DESKTOP_SET UnityWindowId offset
    @endcode
-   @param[in] UnityWindowId UnityWindowId of window to move 
+   @param[in] UnityWindowId UnityWindowId of window to move
    @param[in] offset Offset into desktop configuration, as defined by
-                     @ref UNITY_RPC_DESKTOP_CONFIG_SET, 0 or greater. 
+                     @ref UNITY_RPC_DESKTOP_CONFIG_SET, 0 or greater.
    @}
 */
 
@@ -737,64 +753,64 @@ desktop where the upper right <tt>{1,2}</tt> is the currently active desktop.
    @{
 
    @def         UNITY_RPC_PUSH_UPDATE_CMD
-   @brief       Send a round of Unity Window Tracker updates to the host. 
+   @brief       Send a round of Unity Window Tracker updates to the host.
    @todo doucment update format in unityWindowTracker.c
-   @code 
+   @code
    UNITY_RPC_PUSH_UPDATE_CMD commands
    @endcode
    @param[in]   A double-NUL-terminated string containing NUL-delimited update commands.
    @note        Updates are followed in the command string by Z-order information,
-                and active desktop information. The update format is documented in 
-                @ref unityWindowTracker.c 
+                and active desktop information. The update format is documented in
+                @ref unityWindowTracker.c
 
 
-   @def         UNITY_RPC_VMX_SHOW_TASKBAR        
+   @def         UNITY_RPC_VMX_SHOW_TASKBAR
    @brief       Ask the host to send its "show taskbar" setting.
-   @code 
-   UNITY_RPC_VMX_SHOW_TASKBAR 
+   @code
+   UNITY_RPC_VMX_SHOW_TASKBAR
    @endcode
 
 
-   @def         UNITY_RPC_UNITY_CAP               
-   @brief       Tell the host if the guest is capable of supporting Unity or not. 
-   @code 
+   @def         UNITY_RPC_UNITY_CAP
+   @brief       Tell the host if the guest is capable of supporting Unity or not.
+   @code
    UNITY_RPC_UNITY_CAP flag
    @endcode
-   @param[in] flag If 1, guest supports Unity. If 0, it does not 
+   @param[in] flag If 1, guest supports Unity. If 0, it does not
 
-   @def         UNITY_RPC_SHOW_TASKBAR_CAP        
+   @def         UNITY_RPC_SHOW_TASKBAR_CAP
    @brief       Tells the host if the guest is capable of showing and hiding the
-                taskbar. 
-   @code 
+                taskbar.
+   @code
    UNITY_RPC_SHOW_TASKBAR_CAP flag
    @endcode
-   @param[in] flag If 1, taskbar visibility can be controlled. If 0, it cannot 
+   @param[in] flag If 1, taskbar visibility can be controlled. If 0, it cannot
 
-   @def         GHI_RPC_LAUNCHMENU_CHANGE         
+   @def         GHI_RPC_LAUNCHMENU_CHANGE
    @brief       Inform the host that one or more launch menu items have changed.
    @todo        Move this define to a GHI-specific header.
-   @code 
-   GHI_RPC_LAUNCHMENU_CHANGE 
+   @code
+   GHI_RPC_LAUNCHMENU_CHANGE
    @endcode
 
 
-   @def         GHI_RPC_PROTOCOL_HANDLER_INFO     
-   @brief       This command sends the list of protocol handlers to the host. 
+   @def         GHI_RPC_PROTOCOL_HANDLER_INFO
+   @brief       This command sends the list of protocol handlers to the host.
    @todo        Move this define to a GHI-specific header.
-   @code 
-   GHI_RPC_PROTOCOL_HANDLER_INFO 
+   @code
+   GHI_RPC_PROTOCOL_HANDLER_INFO
    @endcode
    @param data XDR data containing protocol handler info.
    @sa GHIPlatformGetProtocolHandlers for platform-specific list of handled protocols.
    @sa ghiProtocolHandler.x for XDR data format.
 
 
-   @def         UNITY_RPC_UNITY_ACTIVE            
-   @brief       Tell host we are entering or leaving Unity mode. 
-   @code 
+   @def         UNITY_RPC_UNITY_ACTIVE
+   @brief       Tell host we are entering or leaving Unity mode.
+   @code
    UNITY_RPC_UNITY_ACTIVE flag
    @endcode
-   @param[in] flag If 1, Unity is active. If 0, Unity is not active 
+   @param[in] flag If 1, Unity is active. If 0, Unity is not active
 
    @}
 */
@@ -820,8 +836,12 @@ desktop where the upper right <tt>{1,2}</tt> is the currently active desktop.
  *
  * Each string in the list has one of the following formats:
  *
- * @li <tt>"add" UnityWindowId</tt> @par
+ * @li <tt>"add" UnityWindowId arguments</tt> @par
  *    A window identified by @a UnityWindowId has just been created.
+ *    The @a arguments are optional, and are not provided by all Tools.
+ *    Arguments are space-separated key=value pairs, with the following
+ *    keys: windowPath, execPath. The values are the same as what is
+ *    returned by the @ref UNITY_RPC_GET_WINDOW_PATH RPC.
  *
  * @li <tt>"remove" UnityWindowId</tt> @par
  *    The window identified by @a UnityWindowId has been removed.  Get rid
index 3d668c5b0306ae7b3da22bec3d61ca34071ddb42..d0961f53d2e1fb2ea90e1b90d1cee944da4f44bf 100644 (file)
@@ -119,6 +119,8 @@ typedef struct UnityUpdate {
    union {
       struct {
          UnityWindowId     id;
+         DynBuf            windowPathUtf8;
+         DynBuf            execPathUtf8;
       } addWindow;
 
       struct {
@@ -199,6 +201,8 @@ typedef struct {
    uint32            state;
    UnityWindowType   type;
    UnityDesktopId    desktopId;
+   DynBuf            windowPathUtf8;
+   DynBuf            execPathUtf8;
 
    /* Each element is an OR of the UNITY_INFO_ATTR_* values */
    unsigned char     attributes[UNITY_MAX_ATTRIBUTES];
@@ -241,6 +245,13 @@ struct _UnityWindowTracker {
    UnityDesktopId activeDesktopId;
    Bool           activeDesktopChanged;
 
+   /*
+    * True if the guest should add hidden windows to the list of tracked windows.
+    * The windows will be added to the tracker with the hidden attribute.
+    * By default the guest will not add hidden windows to the tracker.
+    */
+   Bool           addHiddenWindows;
+
    void           *cbparam;
    UnityUpdateCallback cb;
    uint32         updateFlags;
@@ -258,9 +269,13 @@ void UnityWindowTracker_Cleanup(UnityWindowTracker *tracker);
 void UnityWindowTracker_SetDataFreeFunc(UnityWindowTracker *tracker,
                                         UnityDataFreeFunc freeFn);
 UnityWindowInfo *UnityWindowTracker_AddWindow(UnityWindowTracker *tracker,
-                                              UnityWindowId id);
+                                              UnityWindowId id,
+                                              DynBuf *windowPathUtf8,
+                                              DynBuf *execPathUtf8);
 UnityWindowInfo *UnityWindowTracker_AddWindowWithData(UnityWindowTracker *tracker,
                                                       UnityWindowId id,
+                                                      DynBuf *windowPathUtf8,
+                                                      DynBuf *execPathUtf8,
                                                       void *data);
 void UnityWindowTracker_MoveWindow(UnityWindowTracker *tracker,
                                    UnityWindowId id, int x1, int y1, int x2,
index 18d03e0a2f6f5c0270ed5fc13b4863bd0be7a695..6d327cf6e5633371e0bbad01889cda471da976c8 100644 (file)
@@ -146,6 +146,12 @@ int Util_CompareDotted(const char *s1, const char *s2);
 void Util_PrintLoadedObjects(void *addr_inside_exec);
 #endif
 
+#if defined(VMX86_STATS)
+Bool Util_QueryCStResidency(uint32 *numCpus, uint32 *numCStates,
+                            uint64 **transitns, uint64 **residency,
+                            uint64 **transTime, uint64 **residTime);
+#endif
+
 /*
  * In util_shared.h
  */
@@ -223,6 +229,7 @@ EXTERN Bool Util_MakeSureDirExistsAndAccessible(char const *path,
 #else
 #   define DIRSEPS           "/"
 #   define DIRSEPC           '/'
+#   define VALID_DIRSEPS      DIRSEPS
 #endif
 
 
index 3a76d43d11e96d323ea6e12fe97bccfa0eb38d30..044fba71884dd8c6479d200858d6bfceb633d7f9 100644 (file)
@@ -164,6 +164,8 @@ enum {
    VIX_E_UNABLE_TO_REPLAY_VM                    = 3039,
    VIX_E_CANNOT_POWER_ON_VM                     = 3041,
    VIX_E_NO_DISPLAY_SERVER                      = 3043,
+   VIX_E_VM_NOT_RECORDING                       = 3044,
+   VIX_E_VM_NOT_REPLAYING                       = 3045,
 
    /* VM Errors */ 
    VIX_E_VM_NOT_FOUND                           = 4000,
index 55164dbcd33bb6f170031fb063646db610bca40f..4f3cd39ca0fde1212be64927d0f53696eae04a91 100644 (file)
@@ -26,7 +26,7 @@
 #define _VIX_COMMANDS_H_
 
 #include "vm_version.h"
-#include "vix.h"
+#include "vixOpenSource.h"
 
 /*
  * These describe the format of the message objects.
@@ -578,8 +578,6 @@ enum VixKeyStrokeModifiers {
    VIX_KEYSTROKE_MODIFIER_CONTROL           = 0x04,
    VIX_KEYSTROKE_MODIFIER_SHIFT             = 0x08,
    VIX_KEYSTROKE_MODIFIER_ALT               = 0x10,
-   VIX_KEYSTROKE_MODIFIER_CAPS_LOCK         = 0x20,
-   VIX_KEYSTROKE_MODIFIER_NUM_LOCK          = 0x40,
    VIX_KEYSTROKE_MODIFIER_KEY_DOWN_ONLY     = 0x80,
    VIX_KEYSTROKE_MODIFIER_KEY_UP_ONLY       = 0x100,
 };
@@ -1043,6 +1041,19 @@ struct VixMsgSetSnapshotInfoResponse {
 #include "vmware_pack_end.h"
 VixMsgSetSnapshotInfoResponse;
 
+typedef
+#include "vmware_pack_begin.h"
+struct VixMsgRemoveBulkSnapshotRequest {
+   VixCommandRequestHeader    header;
+
+   int32                      options;
+   int32                      numSnapshots;
+   /*
+    * This is followed by numSnapshots snapshotIDs.
+    */
+}
+#include "vmware_pack_end.h"
+VixMsgRemoveBulkSnapshotRequest;
 
 /*
  * Rolling Tier operations.
@@ -2131,6 +2142,24 @@ struct VixCommandListFileSystemsRequest {
 VixCommandListFileSystemsRequest;
 
 
+/*
+ * **********************************************************
+ * A simple request packet that contains an options field and a
+ * property list.
+ */
+
+typedef
+#include "vmware_pack_begin.h"
+struct VixCommandGenericRequest {
+   VixCommandRequestHeader    header;
+
+   uint32                     options;
+   uint32                     propertyListSize;
+   // This is followed by the buffer of serialized properties
+}
+#include "vmware_pack_end.h"
+VixCommandGenericRequest;
+
 
 /*
  * These are values we use to discover hosts and guests through SLPv2.
@@ -2261,7 +2290,7 @@ enum {
    VIX_COMMAND_SET_FILE_INFO                    = 95,
    VIX_COMMAND_MOUSE_EVENTS                     = 96,
    VIX_COMMAND_OPEN_TEAM                        = 97,
-   VIX_COMMAND_FIND_HOST_DEVICES                = 98,
+   /* DEPRECATED VIX_COMMAND_FIND_HOST_DEVICES                = 98, */
    VIX_COMMAND_ANSWER_MESSAGE                   = 99,
    VIX_COMMAND_ENABLE_SHARED_FOLDERS            = 100,
    VIX_COMMAND_MOUNT_HGFS_FOLDERS               = 101,
@@ -2280,16 +2309,8 @@ enum {
 
    VIX_COMMAND_STOP_SNAPSHOT_LOG_RECORDING      = 113,
    VIX_COMMAND_STOP_SNAPSHOT_LOG_PLAYBACK       = 114,
-   /*
-    * HOWTO: Adding a new Vix Command. Step 2a.
-    *
-    * Add a new ID for your new function prototype here. BE CAREFUL. The
-    * OFFICIAL list of id's is in the bfg-main tree, in bora/lib/public/vixCommands.h.
-    * When people add new command id's in different tree, they may collide and use
-    * the same ID values. This can merge without conflicts, and cause runtime bugs.
-    * Once a new command is added here, a command info field needs to be added
-    * in bora/lib/foundryMsg. as well.
-    */
+
+
    VIX_COMMAND_SAMPLE_COMMAND                   = 115,
 
    VIX_COMMAND_GET_GUEST_NETWORKING_CONFIG      = 116,
@@ -2367,7 +2388,23 @@ enum {
 
    VIX_COMMAND_LIST_FILESYSTEMS                 = 169,
 
-   VIX_COMMAND_LAST_NORMAL_COMMAND              = 170,
+   VIX_COMMAND_CHANGE_DISPLAY_TOPOLOGY          = 170,
+
+   VIX_COMMAND_SUSPEND_AND_RESUME               = 171,
+
+   VIX_COMMAND_REMOVE_BULK_SNAPSHOT             = 172,
+
+   /*
+    * HOWTO: Adding a new Vix Command. Step 2a.
+    *
+    * Add a new ID for your new function prototype here. BE CAREFUL. The
+    * OFFICIAL list of id's is in the bfg-main tree, in bora/lib/public/vixCommands.h.
+    * When people add new command id's in different tree, they may collide and use
+    * the same ID values. This can merge without conflicts, and cause runtime bugs.
+    * Once a new command is added here, a command info field needs to be added
+    * in bora/lib/foundryMsg. as well.
+    */
+   VIX_COMMAND_LAST_NORMAL_COMMAND              = 173,
 
    VIX_TEST_UNSUPPORTED_TOOLS_OPCODE_COMMAND    = 998,
    VIX_TEST_UNSUPPORTED_VMX_OPCODE_COMMAND      = 999,
@@ -2511,6 +2548,18 @@ const char *VixAsyncOp_GetDebugStrForOpCode(int opCode);
 
 VixCommandSecurityCategory VixMsg_GetCommandSecurityCategory(int opCode);
 
+VixError VixMsg_AllocGenericRequestMsg(int opCode,
+                                       uint64 cookie,
+                                       int credentialType,
+                                       const char *userNamePassword,
+                                       int options,
+                                       VixPropertyListImpl *propertyList,
+                                       VixCommandGenericRequest **request);
+
+VixError VixMsg_ParseGenericRequestMsg(const VixCommandGenericRequest *request,
+                                       int *options,
+                                       VixPropertyListImpl *propertyList);
+
 #endif   // VIX_HIDE_FROM_JAVA
 
 
index cbfa50896d4545c47dab2ca23518f6ff339a3416..8ea2646edb8ef359767a4b5b0cecedc1c99c9ab7 100644 (file)
@@ -417,9 +417,9 @@ extern void VixDebugInit(int debugLevel, int apiTraceLevel,
 extern const char *VixDebug_GetFileBaseName(const char *path);
 extern void VixAssert(const char *cond, const char *file, int lineNum);
 
-extern void VixLogError(VixError err, const char *function, int line,
-            const char *fileName, unsigned long threadId, const char *fmt, ...)
-            PRINTF_DECL(6, 7);
+extern VixError VixLogError(VixError err, const char *function, int line,
+                const char *fileName, unsigned long threadId, const char *fmt, ...)
+                PRINTF_DECL(6, 7);
 
 
 /*
index 228c6a7035128ab840a6b851a2fa6b56e2df9f6a..1dc8b446e8043c7c5309ff53885fcead9b749715 100644 (file)
 #endif
 
 
-
-
-/*
- * from linux: usr/include/asm/io.h
- */
-#ifdef __GNUC__
-#ifndef __SLOW_DOWN_IO
-#ifdef SLOW_IO_BY_JUMPING
-#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
-#else
-#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
-#endif
-#endif
-#elif _MSC_VER
-#ifdef SLOW_IO_BY_JUMPING
-#define __SLOW_DOWN_IO __asm jmp SHORT $+2 __asm  jmp SHORT $+2
-#else
-#define __SLOW_DOWN_IO __asm out 80h,al
-#endif
-#else
-#error
-#endif
-
-#ifdef REALLY_SLOW_IO
-#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
-#else
-#define SLOW_DOWN_IO __SLOW_DOWN_IO
-#endif
-
 /*
  * FXSAVE/FXRSTOR
  *     save/restore SIMD/MMX fpu state
index eac3477b42607c8a0709e16534114b357b3cb39b..ae4d0c3db18e680270bab0a93305de3580700549 100644 (file)
@@ -670,6 +670,12 @@ typedef int pid_t;
 #endif
 #endif // _WIN32
 
+#ifdef HOSTED_LG_PG
+#define hosted_lg_pg 1
+#else
+#define hosted_lg_pg 0
+#endif
+
 /*
  ***********************************************************************
  * STRUCT_OFFSET_CHECK --                                    */ /**
index e9df7377d8aee8d6d74a6e9c2e43a1160f092f90..43bc38faca9afc967cef5c74084e43d46460f6e6 100644 (file)
@@ -466,7 +466,14 @@ typedef uint32    PageNum;
 typedef unsigned  MemHandle;
 typedef int32     World_ID;
 
-#define INVALID_WORLD_ID ((World_ID)-1)
+/* !! do not alter the definition of INVALID_WORLD_ID without ensuring
+ * that the values defined in both bora/public/vm_basic_types.h and
+ * lib/vprobe/vm_basic_types.h are the same.  Additionally, the definition
+ * of VMK_INVALID_WORLD_ID in vmkapi_world.h also must be defined with
+ * the same value
+ */
+
+#define INVALID_WORLD_ID ((World_ID)0)
 
 typedef World_ID User_CartelID;
 #define INVALID_CARTEL_ID INVALID_WORLD_ID
index 48ab7ae35dcf4d6c6231d6ed898e2689f0fb22ce..728bd3ef04ab64685dd3dc2695d96d9c164b4e9d 100644 (file)
 #define MAX_ETHERNET_CARDS      10
 
 /************* PCI Passthrough implementation limits ********************/
-#define MAX_PCI_PASSTHRU_DEVICES 2
+#define MAX_PCI_PASSTHRU_DEVICES 6
 
 /************* USB implementation limits ********************************/
 #define MAX_USB_DEVICES_PER_HOST_CONTROLLER 127
index 5c94d4c09b4d4bf16b497efdf6d0ef8870d09a0c..85e7633394533d3d4c178ca3d24098948ce9475e 100644 (file)
@@ -66,6 +66,7 @@
 #define PRODUCT_WORKSTATION_ENTERPRISE_BRIEF_NAME \
          PRODUCT_WORKSTATION_BRIEF_NAME " " "ACE Edition"
 #define PRODUCT_PLAYER_BRIEF_NAME "Player"
+#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"
 
@@ -91,6 +92,7 @@
 #define PRODUCT_CONSOLE_NAME MAKE_NAME("Server Console")
 #define PRODUCT_PLAYER_NAME MAKE_NAME(PRODUCT_PLAYER_BRIEF_NAME)
 #define PRODUCT_PLAYER_NAME_FOR_LICENSE PRODUCT_PLAYER_NAME
+#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_VMLS_SHORT_NAME "VMLS"
index a10bb509a566f244955cb507198905d58e4dc086..7f2397fc33167aafbbc3e073d0c03455dc0bdd63 100644 (file)
@@ -886,6 +886,13 @@ typedef uint32 ToolsVersion;
 #define   TOOLS_VERSION_WS70_BETA1_V_MNR  1
 #define   TOOLS_VERSION_WS70_BETA1_V_BASE 0
 
+#ifndef RC_INVOKED
+#define   TOOLS_VERSION_WS70_BETA2  TOOLS_VERSION_TO_UINT(TOOLS_VERSION_WS70_BETA2_V)
+#endif /* RC_INVOKED */
+#define   TOOLS_VERSION_WS70_BETA2_V_MJR  8
+#define   TOOLS_VERSION_WS70_BETA2_V_MNR  1
+#define   TOOLS_VERSION_WS70_BETA2_V_BASE 1
+
 #ifndef RC_INVOKED
 #define   TOOLS_VERSION_FUSION30_BETA1  TOOLS_VERSION_TO_UINT(TOOLS_VERSION_FUSION30_BETA1_V)
 #endif /* RC_INVOKED */
@@ -893,10 +900,17 @@ typedef uint32 ToolsVersion;
 #define   TOOLS_VERSION_FUSION30_BETA1_V_MNR  2
 #define   TOOLS_VERSION_FUSION30_BETA1_V_BASE 0
 
+#ifndef RC_INVOKED
+#define   TOOLS_VERSION_FUSION30_BETA2  TOOLS_VERSION_TO_UINT(TOOLS_VERSION_FUSION30_BETA2_V)
+#endif /* RC_INVOKED */
+#define   TOOLS_VERSION_FUSION30_BETA2_V_MJR  8
+#define   TOOLS_VERSION_FUSION30_BETA2_V_MNR  2
+#define   TOOLS_VERSION_FUSION30_BETA2_V_BASE 1
+
 
-#define   TOOLS_VERSION_CURRENT        TOOLS_VERSION_WS70_BETA1
-#define   TOOLS_VERSION_CURRENT_STR    TOOLS_VERSION_TO_STR(TOOLS_VERSION_WS70_BETA1)
-#define   TOOLS_VERSION_CURRENT_CSV    TOOLS_VERSION_TO_CSV(TOOLS_VERSION_WS70_BETA1)
+#define   TOOLS_VERSION_CURRENT        TOOLS_VERSION_WS70_BETA2
+#define   TOOLS_VERSION_CURRENT_STR    TOOLS_VERSION_TO_STR(TOOLS_VERSION_WS70_BETA2)
+#define   TOOLS_VERSION_CURRENT_CSV    TOOLS_VERSION_TO_CSV(TOOLS_VERSION_WS70_BETA2)
 
 
 /*
index 45bd868bbb855dc689c0f2f2b269c10d3179ccec..216ab60cd53341a69a8d62d0b07793913338d454 100644 (file)
 #define WBC_VERSION "e.x.p"
 #define SDK_VERSION "4.1.0"
 #define FOUNDRY_VERSION "e.x.p"
-#define FOUNDRY_FILE_VERSION 1,6,2,PRODUCT_BUILD_NUMBER_NUMERIC
+#define FOUNDRY_FILE_VERSION 1,7,0,PRODUCT_BUILD_NUMBER_NUMERIC
 #define VMLS_VERSION "e.x.p"
 #define VLICENSE_VERSION "1.1.0"
 #define DDK_VERSION "e.x.p"
 /*
  * The current Tools version, derived from vm_tools_version.h. Do not modify this.
  */
-#define TOOLS_VERSION "2009.06.18"
+#define TOOLS_VERSION "2009.07.22"
 
 #ifdef VMX86_VPX
 #define VIM_API_TYPE "VirtualCenter"
 #define PRODUCT_VERSION_SCALABLE_SERVER_3 PRODUCT_SCALABLE_SERVER_BRIEF_NAME " 3.x"
 #define PRODUCT_VERSION_SCALABLE_SERVER_30 PRODUCT_SCALABLE_SERVER_BRIEF_NAME " 3.0"
 #define PRODUCT_VERSION_SCALABLE_SERVER_31 PRODUCT_SCALABLE_SERVER_BRIEF_NAME " 3.5"
+#define PRODUCT_VERSION_SCALABLE_SERVER_40 PRODUCT_SCALABLE_SERVER_BRIEF_NAME " 4.0"
 #define PRODUCT_VERSION_WGS_1 PRODUCT_WGS_BRIEF_NAME " 1.x"
 #define PRODUCT_VERSION_WGS_2 PRODUCT_WGS_BRIEF_NAME " 2.0"
 #define PRODUCT_VERSION_GSX_2 PRODUCT_GSX_BRIEF_NAME " 2.x"
 #define PRODUCT_VERSION_WORKSTATION_5 PRODUCT_WORKSTATION_BRIEF_NAME " 5.x"
 #define PRODUCT_VERSION_WORKSTATION_6 PRODUCT_WORKSTATION_BRIEF_NAME " 6.0"
 #define PRODUCT_VERSION_WORKSTATION_65 PRODUCT_WORKSTATION_BRIEF_NAME " 6.5"
+#define PRODUCT_VERSION_WORKSTATION_70 PRODUCT_WORKSTATION_BRIEF_NAME " 7.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"
 #define PRODUCT_VERSION_PLAYER_1 PRODUCT_PLAYER_BRIEF_NAME " 1.x"
 #define PRODUCT_VERSION_MAC_DESKTOP_1 PRODUCT_MAC_DESKTOP_BRIEF_NAME " 1.1"
 #define PRODUCT_VERSION_MAC_DESKTOP_2 PRODUCT_MAC_DESKTOP_BRIEF_NAME " 2.0"
+#define PRODUCT_VERSION_MAC_DESKTOP_3 PRODUCT_MAC_DESKTOP_BRIEF_NAME " 3.0"
 
 
 /*
index 0cc94e67ed7176814ae9d81b91a8ee15fc508f8b..6a00c5a860322bd34c4cee660310589f941936d1 100644 (file)
@@ -46,7 +46,7 @@
  * @param[in]  err      Error code. Must not be 0.
  */
 #define VMTOOLSAPP_ERROR(ctx, err) do {   \
-   g_assert((err) != 0);                  \
+   ASSERT((err) != 0);                    \
    (ctx)->errorCode = (err);              \
    g_main_loop_quit((ctx)->mainLoop);     \
 } while (0)
 #endif
 
 
+/**
+ * This enum lists all API versions that different versions of vmtoolsd support.
+ * The "ToolsAppCtx" instance provided to plugins contains a "version" field
+ * which is a bit-mask of these values, telling plugins what features the
+ * container supports.
+ *
+ * Refer to a specific feature's documentation for which version of the API
+ * is needed for it to be supported.
+ */
+typedef enum {
+   TOOLS_CORE_API_V1    = 0x1,
+} ToolsCoreAPI;
+
+
 /**
  * Defines the context of a tools application. This data is provided by the
  * core services to applications when they're loaded.
  */
 typedef struct ToolsAppCtx {
+   /** Supported API versions. This is a bit-mask. */
+   ToolsCoreAPI      version;
    /** Name of the application. */
    const gchar      *name;
    /** Whether we're running under a VMware hypervisor. */
@@ -243,10 +259,80 @@ typedef enum {
     * Denotes a list of signals the application is interested in (type
     * ToolsPluginSignalCb).
     */
-   TOOLS_APP_SIGNALS    = 2
+   TOOLS_APP_SIGNALS    = 2,
+   /**
+    * Denotes an application provider (type ToolsAppProvider). This allows
+    * plugins to extend the functionality of vmtoolsd by adding new application
+    * types (that other plugins can hook into).
+    */
+   TOOLS_APP_PROVIDER   = 3,
 } ToolsAppType;
 
 
+/**
+ * Defines the registration data for an "application provider". Application
+ * providers allow plugins to hook into new application frameworks that will
+ * be then managed by vmtoolsd - for example, an HTTP server or a dbus endpoint.
+ *
+ * Application providers will be loaded during startup but not activated until
+ * at least one plugin provides registration data for that provider.
+ */
+typedef struct ToolsAppProvider {
+   /** A name describing the provider. */
+   const gchar   *name;
+   /**
+    * Application type. Optimally, new providers would request a new type to be
+    * added to the "official" ToolsAppType enum declared above, although that
+    * is not strictly necessary. Providers should at least try to choose an
+    * unused value.
+    */
+   ToolsAppType   regType;
+   /** Size of the registration structure for this provider. */
+   size_t         regSize;
+   /**
+    * Activation callback (optional). This is called when vmtoolsd detects that
+    * there is at least one application that needs to be registered with this
+    * provider.
+    *
+    * @param[in]  ctx   The application context.
+    * @param[in]  prov  The provider instance.
+    * @param[out] err   Where to store any error information.
+    */
+   void (*activate)(ToolsAppCtx *ctx, struct ToolsAppProvider *prov, GError **err);
+   /**
+    * Registration callback. This is called after "activate", to register an
+    * application provided by a plugin.
+    *
+    * @param[in]  ctx   The application context.
+    * @param[in]  prov  The provider instance.
+    * @param[in]  reg   The application registration data.
+    */
+   void (*registerApp)(ToolsAppCtx *ctx, struct ToolsAppProvider *prov, gpointer reg);
+   /**
+    * Shutdown callback (optional). Called when the service is being shut down.
+    * The provider is responsible for keeping track of registrations and
+    * cleaning them up during shutdown.
+    *
+    * @param[in]  ctx   The application context.
+    * @param[in]  prov  The provider instance.
+    */
+   void (*shutdown)(ToolsAppCtx *ctx, struct ToolsAppProvider *prov);
+   /**
+    * Debugging callback (optional). This callback is called when dumping the
+    * service state to the logs for debugging purposes.
+    *
+    * This callback is called once with a "NULL" reg, so that the provider can
+    * log its internal state, and then once for each registration struct
+    * provided by loaded plugins.
+    *
+    * @param[in]  ctx   The application context.
+    * @param[in]  prov  The provider instance.
+    * @param[in]  reg   The application registration data.
+    */
+   void (*dumpState)(ToolsAppCtx *ctx, struct ToolsAppProvider *prov, gpointer reg);
+} ToolsAppProvider;
+
+
 /**
  * Defines a "transport-specific" registration. The array contains data specific
  * to a "transport" implementation.
@@ -284,11 +370,11 @@ typedef struct ToolsPluginSignalCb {
  * about all functionality exported by the application, and any events that the
  * application may be interested in.
  *
- * All fields are optional. When the plugin is shut down, if the @a regs field
- * is not NULL, it (and its element array) are freed with g_array_free().
+ * When the plugin is shut down, if the @a regs field is not NULL, it (and its
+ * element array) are freed with g_array_free().
  */
 typedef struct ToolsPluginData {
-   /** Name of the application. */
+   /** Name of the application (required). */
    char                      *name;
    /** List of features provided by the app. */
    GArray                    *regs;
index fb2da3676bf5d646ca4fb25e6151233f28026853..25d15c8421d38c7570447bdcff8e39bf4d711533 100644 (file)
@@ -49,8 +49,6 @@ typedef enum {
 #define NATIVE_MAX_PATH 256
 #define MAX_WIPER_FILE_SIZE (2 << 30)   /* The maximum wiper file size in bytes */
 
-#define WIPER_DEVICE_MAPPER_STRING  "Device mapper partition"
-
 typedef struct WiperPartition {
    unsigned char mountPoint[NATIVE_MAX_PATH];
 
index 2dd7471104a024698560082a6b003dab17585f9e..223060392220d0e22e986caaf362b934f2d7af2d 100644 (file)
@@ -116,6 +116,7 @@ CPUIDQuery;
 #define CPUID_CACHED_LEVELS                     \
    CPUIDLEVEL(TRUE,  0,  0)                     \
    CPUIDLEVEL(TRUE,  1,  1)                     \
+   CPUIDLEVEL(FALSE, 5,  5)                     \
    CPUIDLEVEL(FALSE,400, 0x40000000)            \
    CPUIDLEVEL(FALSE,410, 0x40000010)            \
    CPUIDLEVEL(FALSE, 80, 0x80000000)            \
@@ -125,7 +126,6 @@ CPUIDQuery;
 
 #define CPUID_UNCACHED_LEVELS                   \
    CPUIDLEVEL(FALSE, 4, 4)                      \
-   CPUIDLEVEL(FALSE, 5, 5)                      \
    CPUIDLEVEL(FALSE, 6, 6)                      \
    CPUIDLEVEL(FALSE, A, 0xA)                    \
    CPUIDLEVEL(FALSE, 86, 0x80000006)            \
@@ -179,6 +179,7 @@ typedef enum {
 #define CPUID_CYRIX_VENDOR_STRING       "CyriteadxIns"
 #define CPUID_VIA_VENDOR_STRING         "CentaulsaurH"
 #define CPUID_HYPERV_HYPERVISOR_VENDOR_STRING  "Microsoft Hv"
+#define CPUID_VMWARE_HYPERVISOR_VENDOR_STRING  "VMwareVMware"
 #define CPUID_INTEL_VENDOR_STRING_FIXED "GenuineIntel"
 #define CPUID_AMD_VENDOR_STRING_FIXED   "AuthenticAMD"
 #define CPUID_CYRIX_VENDOR_STRING_FIXED "CyrixInstead"
@@ -279,7 +280,7 @@ FIELDDEFA( 1, EBX, COMMON, 24,  8, APICID,              ANY, IGNORE, 0, FALSE, A
 FLAGDEFA(  1, ECX, COMMON, 0,   1, SSE3,                YES, HOST,   0, TRUE,  SSE3)      \
 FLAGDEFA(  1, ECX, INTEL,  1,   1, PCLMULQDQ,           YES, HOST,   0, TRUE, PCLMULQDQ)  \
 FLAGDEF(   1, ECX, INTEL,  2,   1, NDA2,                NO,  MASK,   0, FALSE)            \
-FLAGDEFA(  1, ECX, COMMON, 3,   1, MWAIT,               NO,  MASK,   0, FALSE, MWAIT)     \
+FLAGDEFA(  1, ECX, COMMON, 3,   1, MWAIT,               ANY, MASK,   0, FALSE, MWAIT)     \
 FLAGDEFA(  1, ECX, INTEL,  4,   1, DSCPL,               NO,  MASK,   0, FALSE, DSCPL)     \
 FLAGDEFA(  1, ECX, INTEL,  5,   1, VMX,                 NO,  MASK,   0, FALSE, VMX)       \
 FLAGDEF(   1, ECX, INTEL,  6,   1, SMX,                 NO,  MASK,   0, FALSE) \
@@ -344,10 +345,10 @@ FIELDDEF(  4, EBX, INTEL,  22, 10, CACHE_WAYS,          NA,  IGNORE, 0, FALSE)
 
 /*     LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, MASK TYPE, SET TO, CPL3, [FUNC] */
 #define CPUID_FIELD_DATA_LEVEL_5                                           \
-FIELDDEF(  5, EAX, COMMON,  0, 16, MWAIT_MIN_SIZE,      NA,  IGNORE, 0, FALSE) \
-FIELDDEF(  5, EBX, COMMON,  0, 16, MWAIT_MAX_SIZE,      NA,  IGNORE, 0, FALSE) \
+FIELDDEFA( 5, EAX, COMMON,  0, 16, MWAIT_MIN_SIZE,      NA,  IGNORE, 0, FALSE, MWAIT_MIN_SIZE) \
+FIELDDEFA( 5, EBX, COMMON,  0, 16, MWAIT_MAX_SIZE,      NA,  IGNORE, 0, FALSE, MWAIT_MAX_SIZE) \
 FLAGDEF(   5, ECX, COMMON,  0,  1, MWAIT_EXTENSIONS,    NA,  IGNORE, 0, FALSE) \
-FLAGDEF(   5, ECX, COMMON,  1,  1, MWAIT_INTR_BREAK,    NA,  IGNORE, 0, FALSE) \
+FLAGDEFA(  5, ECX, COMMON,  1,  1, MWAIT_INTR_BREAK,    NA,  IGNORE, 0, FALSE, MWAIT_INTR_BREAK) \
 FIELDDEF(  5, EDX, INTEL,   0,  4, MWAIT_C0_SUBSTATE,   NA,  IGNORE, 0, FALSE) \
 FIELDDEF(  5, EDX, INTEL,   4,  4, MWAIT_C1_SUBSTATE,   NA,  IGNORE, 0, FALSE) \
 FIELDDEF(  5, EDX, INTEL,   8,  4, MWAIT_C2_SUBSTATE,   NA,  IGNORE, 0, FALSE) \
@@ -863,31 +864,6 @@ CPUID_MODEL_IS_BARCELONA(uint32 v) // IN: %eax from CPUID with %eax=1.
 #define CPUID_INTEL_ID4EAX_CACHE_FULLY_ASSOC    0x00000200
 
 
-/*
- * On AMD chips before Opteron and Intel chips before P4 model 3,
- * WRMSR(TSC) clears the upper half of the TSC instead of using %edx.
- */
-static INLINE Bool
-CPUID_FullyWritableTSC(CpuidVendors vendor, // IN
-                       uint32 v)      // IN: %eax from CPUID with %eax=1.
-{
-   /*
-    * Returns FALSE if:
-    *   - Intel && P6 (pre-core) or
-    *   - Intel && P4 (model < 3) or
-    *   - AMD && pre-K8 Opteron
-    * Otherwise, returns TRUE (including for Via Nano).
-    */
-   return !((vendor == CPUID_VENDOR_INTEL &&
-             ((CPUID_FAMILY_IS_P6(v) &&
-               CPUID_EFFECTIVE_MODEL(v) < CPUID_MODEL_PM_0E) ||
-              (CPUID_FAMILY_IS_PENTIUM4(v) &&
-               CPUID_EFFECTIVE_MODEL(v) < 3))) ||
-            (vendor == CPUID_VENDOR_AMD &&
-             CPUID_FAMILY(v) < CPUID_FAMILY_K8));
-}
-
-
 /*
  * For certain AMD processors, an lfence instruction is necessary at various
  * places to ensure ordering.
@@ -930,44 +906,6 @@ CPUID_RequiresFence(CpuidVendors vendor, // IN
 }
 
 
-/*
- *----------------------------------------------------------------------
- *
- * CPUID_CountsCPUIDAsBranch --
- *
- *      Returns TRUE iff the cpuid given counts CPUID as a branch
- *      (i.e. is a pre-Merom E CPU).
- *
- *----------------------------------------------------------------------
- */
-
-static INLINE Bool
-CPUID_CountsCPUIDAsBranch(uint32 v) /* %eax from CPUID with %eax=1 */
-{
-   /* 
-    * CPUID no longer a branch starting with Merom E. Bug 148411.
-    * Penryn (Extended Model: 1) also has this fixed.
-    *
-    * Merom E is: CPUID.1.eax & 0xfff = 0x6f9
-    */
-   return !(CPUID_FAMILY_IS_P6(v) &&
-            (CPUID_EFFECTIVE_MODEL(v) > CPUID_MODEL_CORE_0F ||
-             (CPUID_EFFECTIVE_MODEL(v) == CPUID_MODEL_CORE_0F &&
-              CPUID_STEPPING(v) >= 9)));
-}
-
-/*
- * On Merom and later Intel chips, not present PDPTEs with reserved bits
- * set do not fault with a #GP. See PR# 109120.
- */
-static INLINE Bool
-CPUID_FaultOnNPReservedPDPTE(uint32 v) // IN: %eax from CPUID with %eax=1.
-{
-   return !(CPUID_FAMILY_IS_P6(v) &&
-            (CPUID_EFFECTIVE_MODEL(v) >= CPUID_MODEL_CORE_0F));
-}
-
-
 /* 
  * The following low-level functions compute the number of
  * cores per cpu.  They should be used cautiously because
@@ -983,6 +921,7 @@ CPUID_IntelCoresPerPackage(uint32 v) /* %eax from CPUID with %eax=4 and %ecx=0.
    return 1 + CPUID_INTEL_CORE_COUNT(v);
 }
 
+
 static INLINE uint32
 CPUID_AMDCoresPerPackage(uint32 v) /* %ecx from CPUID with %eax=0x80000008. */
 {
@@ -990,6 +929,7 @@ CPUID_AMDCoresPerPackage(uint32 v) /* %ecx from CPUID with %eax=0x80000008. */
    return 1 + CPUID_AMD_CORE_COUNT(v);
 }
 
+
 /*
  * Hypervisor CPUID space is 0x400000XX.
  */
@@ -1001,20 +941,4 @@ CPUID_IsHypervisorLevel(uint32 level, uint32 *offset)
 }
 
 
-/* Intel and VIA allow use of sysenter/sysexit in longmode. AMD does not. */
-#define CPUID_HAS_SYSENTER64()  (!CPUFEATURE_IS_AMD())
-
-/* Intel and VIA behave the same, AMD is different. */
-#define CPUID_LOADING_NULL_LEAVES_BASE()   CPUFEATURE_IS_AMD()
-
-/* Intel and VIA ignore <op> on 64 bit JMPs. */
-#define CPUID_JMP64_IGNORES_OPSZ()  (!CPUFEATURE_IS_AMD())
-
-/*
- * Hardware-assisted  virtualization supports one of two hypercalls:
- * VMCALL for VT-x implementations (Intel or VIA) and VMMCALL for AMD-V
- * implementations (AMD).
- */
-#define CPUID_HYPERCALL_IS_VMCALL() (!CPUFEATURE_IS_AMD())
-
 #endif
index 9fb25f3db44faaee023d73494638afced2104f37..f9bc451568fe6b4a12e3afdc9b3c43705e53e154 100644 (file)
 
 
 /*
- *----------------------------------------------------------------------
- *
- * DblLnkLst_Init --
- *
- *    Initialize a member of a doubly linked list
- *
- * Result
- *    None
- *
- * Side effects:
- *    None
- *
- *----------------------------------------------------------------------
- */
-
-void
-DblLnkLst_Init(DblLnkLst_Links *l) // IN
-{
-   ASSERT(l);
-
-   l->prev = l->next = l;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * DblLnkLst_Link --
- *
- *    Merge two doubly linked lists into one
- *
- *    The operation is commutative
- *    The operation is inversible (its inverse is DblLnkLst_Unlink)
- *
- * Result
- *    None
- *
- * Side effects:
- *    None
- *
- *----------------------------------------------------------------------
- */
-
-void
-DblLnkLst_Link(DblLnkLst_Links *l1, // IN
-               DblLnkLst_Links *l2) // IN
-{
-   DblLnkLst_Links *tmp;
-
-   ASSERT(l1);
-   ASSERT(l2);
-
-   (tmp      = l1->prev)->next = l2;
-   (l1->prev = l2->prev)->next = l1;
-    l2->prev = tmp                 ;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * DblLnkLst_Unlink --
- *
- *    Split one doubly linked list into two
- *
- *    No check is performed: the caller must ensure that both members
- *    belong to the same doubly linked list
- *
- *    The operation is commutative
- *    The operation is inversible (its inverse is DblLnkLst_Link)
- *
- * Result
- *    None
- *
- * Side effects:
- *    None
- *
- *----------------------------------------------------------------------
+ * XXX This file is empty because I made all the functions inline.
+ * -- edward
  */
 
-void
-DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN
-                 DblLnkLst_Links *l2) // IN
-{
-   DblLnkLst_Links *tmp;
-
-   ASSERT(l1);
-   ASSERT(l2);
-
-   tmp       = l1->prev            ;
-   (l1->prev = l2->prev)->next = l1;
-   (l2->prev = tmp     )->next = l2;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * DblLnkLst_Unlink1 --
- *
- *    Unlink an element from its list.
- *
- * Result
- *    None
- *
- * Side effects:
- *    None
- *
- *----------------------------------------------------------------------
- */
-
-void
-DblLnkLst_Unlink1(DblLnkLst_Links *l) // IN
-{
-   ASSERT(l);
-
-   DblLnkLst_Unlink(l, l->next);
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * DblLnkLst_IsLinked --
- *
- *    Determines whether an element is linked with any other elements.
- *
- * Results:
- *    TRUE if link is linked, FALSE otherwise.
- *
- * Side effects:
- *    None.
- *
- *----------------------------------------------------------------------------
- */
-
-Bool
-DblLnkLst_IsLinked(DblLnkLst_Links const *l) // IN
-{
-   ASSERT(l);
-
-   ASSERT((l->prev == l && l->next == l) ||
-          (l->prev != l && l->next != l));
-
-   /*
-    * A DblLnkLst_Links is either linked to itself (not linked) or linked to
-    * other elements in a list (linked).
-    */
-   return l->prev != l;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * DblLnkLst_LinkFirst --
- *
- *    Insert 'l' at the beginning of the list anchored at 'head'
- *
- * Result
- *    None
- *
- * Side effects:
- *    None
- *
- *----------------------------------------------------------------------
- */
-
-void
-DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN
-                    DblLnkLst_Links *l)    // IN
-{
-   ASSERT(head);
-   ASSERT(l);
-
-   DblLnkLst_Link(head->next, l);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * DblLnkLst_LinkLast --
- *
- *    Insert 'l' at the end of the list anchored at 'head'
- *
- * Result
- *    None
- *
- * Side effects:
- *    None
- *
- *----------------------------------------------------------------------
- */
-
-void
-DblLnkLst_LinkLast(DblLnkLst_Links *head, // IN
-                   DblLnkLst_Links *l)    // IN
-{
-   ASSERT(head);
-   ASSERT(l);
-
-   DblLnkLst_Link(head, l);
-}
-
 
 #if 0
 /*
index bbad998ac0aba2982b26dd53704505e73697563b..6a141ee27e10dec165b35ea54727f22cdf248c20 100644 (file)
@@ -498,6 +498,98 @@ nem:
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Escape_StrChr --
+ *
+ *      Find the first occurence of c in bufIn that is not preceded by
+ *      escByte.
+ *
+ *      XXX Doesn't handle recursive escaping, so <escByte><escByte><c>
+ *          will skip that occurence of <c>
+ *
+ * Results:
+ *      A pointer to the character, if found, NULL if not found.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+const char *
+Escape_Strchr(char escByte,      // IN
+              const char *bufIn, // IN
+              char c)            // IN
+{
+   size_t i;
+   Bool escaped = FALSE;
+
+   ASSERT(escByte != c);
+   ASSERT(bufIn);
+
+   for (i = 0; bufIn[i] != '\0'; i++) {
+      if (escaped) {
+         escaped = FALSE;
+      } else {
+         if (bufIn[i] == c) {
+            return &bufIn[i];
+         }
+
+         if (bufIn[i] == escByte) {
+            escaped = TRUE;
+         }
+      }
+   }
+   return NULL;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Escape_Unescape --
+ *
+ *      Removes all occurences of an escape character from a string, unless
+ *      the occurence is escaped.
+ *
+ * Results:
+ *      An allocated string.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char *
+Escape_Unescape(char escByte,       // IN
+                const char *bufIn)  // IN
+{
+   DynBuf result;
+   Bool escaped = FALSE;
+   char nullbyte = '\0';
+   int i;
+
+   ASSERT(bufIn);
+
+   DynBuf_Init(&result);
+
+   for (i = 0; bufIn[i]; i++) {
+      if (bufIn[i] != escByte || escaped) {
+         DynBuf_Append(&result, &(bufIn[i]), sizeof(char));
+         escaped = FALSE;
+      } else {
+         escaped = TRUE;
+      }
+   }
+
+   DynBuf_Append(&result, &nullbyte, sizeof('\0'));
+   return DynBuf_Get(&result);
+}
+
+
 /*
  *----------------------------------------------------------------------------
  *
index cf61200d00682ae33ea7a9130f9a09c41a9fac8d..ef8beeecc4c0aee9709e45aa1c09499bdb3193b4 100644 (file)
@@ -491,6 +491,36 @@ HashTable_Lookup(HashTable  *ht,      // IN
 Bool
 HashTable_Delete(HashTable  *ht,        // IN/OUT: the hash table
                  const char *keyStr)    // IN: key for the element to remove
+{
+   return HashTable_LookupAndDelete(ht, keyStr, NULL);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HashTable_LookupAndDelete --
+ *
+ *      Look up an element in the hash table, then delete it.
+ *
+ *     If clientData is specified, then the entry data is returned,
+ *     and the free function is not called.
+ *
+ * Results:
+ *      TRUE if the entry was found and subsequently removed
+ *      FALSE otherwise
+ *     Entry value is returned in *clientData.
+ *
+ * Side effects:
+ *     See above
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+HashTable_LookupAndDelete(HashTable *ht,      // IN/OUT: the hash table
+                          const char *keyStr, // IN: key for the element
+                         void **clientData)  // OUT: return data
 {
    uint32 hash = HashTableComputeHash(ht, keyStr);
    HashTableLink *linkp;
@@ -507,7 +537,9 @@ HashTable_Delete(HashTable  *ht,        // IN/OUT: the hash table
         if (ht->copyKey) {
            free((char *) entry->keyStr);
         }
-         if (ht->freeEntryFn) {
+        if (clientData != NULL) {
+            *clientData = Atomic_ReadPtr(&entry->clientData);
+        } else if (ht->freeEntryFn) {
             ht->freeEntryFn(Atomic_ReadPtr(&entry->clientData));
          }
          free(entry);
index f064b2c6d036888c051632db26521da400db341e..e57491ee0d2e05254100c41606b992cdf330be50 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <string.h>
-#include <errno.h>
-#include <sys/time.h>
+#include <ctype.h>
 #include <sys/utsname.h>
+#include <netdb.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <pwd.h>
+#include <sys/resource.h>
 #if defined(sun)
 #include <sys/systeminfo.h>
 #endif
-#include <unistd.h>
-#include <sys/types.h>
 #include <sys/socket.h>
-#include <sys/stat.h>
 #if defined(__FreeBSD__) || defined(__APPLE__)
 # include <sys/sysctl.h>
 #endif
+#if defined(__APPLE__)
+#define SYS_NMLN _SYS_NAMELEN
+#include <assert.h>
+#include <CoreServices/CoreServices.h>
+#include <mach-o/dyld.h>
+#include <mach/host_info.h>
+#include <mach/mach_host.h>
+#include <mach/mach_init.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#elif defined(__FreeBSD__)
+#if !defined(RLIMIT_AS)
+#  if defined(RLIMIT_VMEM)
+#     define RLIMIT_AS RLIMIT_VMEM
+#  else
+#     define RLIMIT_AS RLIMIT_RSS
+#  endif
+#endif
+#else
+#if !defined(USING_AUTOCONF) || defined(HAVE_SYS_VFS_H)
+#include <sys/vfs.h>
+#endif
+#if !defined(sun) && (!defined(USING_AUTOCONF) || (defined(HAVE_SYS_IO_H) && defined(HAVE_SYS_SYSINFO_H)))
+#include <sys/io.h>
+#include <sys/sysinfo.h>
+#ifndef HAVE_SYSINFO
+#define HAVE_SYSINFO 1
+#endif
+#endif
+#endif
+
+#if defined(__APPLE__) || defined(__FreeBSD__)
+#include <paths.h>
+#endif
+
+#if !defined(_PATH_DEVNULL)
+#define _PATH_DEVNULL "/dev/null"
+#endif
 
 #include "vmware.h"
+#include "hostType.h"
 #include "hostinfo.h"
 #include "safetime.h"
+#include "vm_version.h"
 #include "str.h"
+#include "msg.h"
+#include "log.h"
+#include "posix.h"
+#include "file.h"
+#include "backdoor_def.h"
+#include "util.h"
+#include "vmstdio.h"
+#include "su.h"
+#include "vm_atomic.h"
+#include "x86cpuid.h"
+#include "syncMutex.h"
+#include "unicode.h"
 #include "guest_os.h"
 #include "dynbuf.h"
-#include "vmstdio.h"
-#include "posix.h"
+
+#if defined(VMX86_SERVER)
+#include "uwvmkAPI.h"
+#include "uwvmk.h"
+#include "vmkSyscall.h"
+#endif
+
+#define LGPFX "HOSTINFO:"
+#define MAX_LINE_LEN 128
 
 #define SYSTEM_BITNESS_32 "i386"
 #define SYSTEM_BITNESS_64_SUN "amd64"
@@ -315,8 +382,8 @@ Hostinfo_GetSystemBitness(void)
 
    if (strcmp(buf, SYSTEM_BITNESS_32) == 0) {
       return 32;
-   } else if (   strcmp(buf, SYSTEM_BITNESS_64_SUN) == 0
-              || strcmp(buf, SYSTEM_BITNESS_64_LINUX) == 0) {
+   } else if (strcmp(buf, SYSTEM_BITNESS_64_SUN) == 0 ||
+              strcmp(buf, SYSTEM_BITNESS_64_LINUX) == 0) {
       return 64;
    }
 
@@ -354,6 +421,7 @@ HostinfoGetOSShortName(char *distro,         // IN: full distro name
 
    if (distroLower == NULL) {
       Warning("%s: could not allocate memory\n", __FUNCTION__);
+
       return;
    }
 
@@ -375,7 +443,8 @@ HostinfoGetOSShortName(char *distro,         // IN: full distro name
          if (releaseStart) {
             sscanf(releaseStart, "release %d", &release);
             if (release > 0) {
-               snprintf(distroShort, distroShortSize, STR_OS_RED_HAT_EN"%d", release);
+               snprintf(distroShort, distroShortSize, STR_OS_RED_HAT_EN"%d",
+                        release);
             }
          }
 
@@ -416,6 +485,12 @@ HostinfoGetOSShortName(char *distro,         // IN: full distro name
       Str_Strcpy(distroShort, STR_OS_ARCH, distroShortSize);
    } else if (strstr(distroLower, "arklinux")) {
       Str_Strcpy(distroShort, STR_OS_ARKLINUX, distroShortSize);
+   } else if (strstr(distroLower, "asianux server 3") ||
+              strstr(distroLower, "asianux client 3")) {
+      Str_Strcpy(distroShort, STR_OS_ASIANUX_3, distroShortSize);
+   } else if (strstr(distroLower, "asianux server 4") ||
+              strstr(distroLower, "asianux client 4")) {
+      Str_Strcpy(distroShort, STR_OS_ASIANUX_4, distroShortSize);
    } else if (strstr(distroLower, "aurox")) {
       Str_Strcpy(distroShort, STR_OS_AUROX, distroShortSize);
    } else if (strstr(distroLower, "black cat")) {
@@ -425,7 +500,11 @@ HostinfoGetOSShortName(char *distro,         // IN: full distro name
    } else if (strstr(distroLower, "conectiva")) {
       Str_Strcpy(distroShort, STR_OS_CONECTIVA, distroShortSize);
    } else if (strstr(distroLower, "debian")) {
-      Str_Strcpy(distroShort, STR_OS_DEBIAN, distroShortSize);
+      if (strstr(distroLower, "4.0")) {
+         Str_Strcpy(distroShort, STR_OS_DEBIAN_4, distroShortSize);
+      } else if (strstr(distroLower, "5.0")) {
+         Str_Strcpy(distroShort, STR_OS_DEBIAN_5, distroShortSize);
+      }
    } else if (strstr(distroLower, "fedora")) {
       Str_Strcpy(distroShort, STR_OS_FEDORA, distroShortSize);
    } else if (strstr(distroLower, "gentoo")) {
@@ -498,6 +577,7 @@ HostinfoReadDistroFile(char *filename,  // IN: distro version file name
 
    if ((fd = open(filename, O_RDONLY)) < 0) {
       Warning("%s: could not open file%s: %d\n", __FUNCTION__, filename, errno);
+
       return FALSE;
    }
 
@@ -517,11 +597,13 @@ HostinfoReadDistroFile(char *filename,  // IN: distro version file name
    if (distroOrig == NULL) {
       Warning("%s: could not allocate memory\n", __FUNCTION__);
       close(fd);
+
       return FALSE;
    }
 
    if (read(fd, distroOrig, buf_sz) != buf_sz) {
-      Warning("%s: could not read file %s: %d\n", __FUNCTION__, filename, errno);
+      Warning("%s: could not read file %s: %d\n", __FUNCTION__, filename,
+              errno);
       goto out;
    }
 
@@ -689,12 +771,14 @@ Hostinfo_GetOSName(uint32 outBufFullLen,  // IN: length of osNameFull buffer
 
    if (uname(&buf) < 0) {
       Warning("%s: uname failed %d\n", __FUNCTION__, errno);
+
       return FALSE;
    }
 
 
    if (strlen(buf.sysname) + strlen(buf.release) + 3 > outBufFullLen) {
       Warning("%s: Error: buffer too small\n", __FUNCTION__);
+
       return FALSE;
    }
 
@@ -731,8 +815,7 @@ Hostinfo_GetOSName(uint32 outBufFullLen,  // IN: length of osNameFull buffer
       }
 
       /*
-       * Try to get OS detailed information
-       * from the lsb_release command.
+       * Try to get OS detailed information from the lsb_release command.
        */
 
       lsbOutput = HostinfoGetCmdOutput(lsbCmd);
@@ -756,13 +839,14 @@ Hostinfo_GetOSName(uint32 outBufFullLen,  // IN: length of osNameFull buffer
 
          if (distroArray[i].filename == NULL) {
             Warning("%s: Error: no distro file found\n", __FUNCTION__);
+
             return FALSE;
          }
       } else {
          char *lsbStart = lsbOutput;
          char *quoteEnd = NULL;
 
-         if (lsbStart[0] == '"') {
+         if (lsbStart[1] == '"') {
             lsbStart++;
             quoteEnd = strchr(lsbStart, '"');
             if (quoteEnd) {
@@ -777,6 +861,7 @@ Hostinfo_GetOSName(uint32 outBufFullLen,  // IN: length of osNameFull buffer
 
       if (strlen(distro) + strlen(osNameFull) + 2 > outBufFullLen) {
          Warning("%s: Error: buffer too small\n", __FUNCTION__);
+
          return FALSE;
       }
 
@@ -785,6 +870,7 @@ Hostinfo_GetOSName(uint32 outBufFullLen,  // IN: length of osNameFull buffer
 
       if (strlen(distroShort) + 1 > outBufLen) {
          Warning("%s: Error: buffer too small\n", __FUNCTION__);
+
          return FALSE;
       }
 
@@ -806,7 +892,8 @@ Hostinfo_GetOSName(uint32 outBufFullLen,  // IN: length of osNameFull buffer
       }
 
       if (nameLen + releaseLen + 1 > outBufLen) {
-         Warning("GuestInfoGetOSName: Error: buffer too small\n");
+         Warning("%s: Error: buffer too small\n", __FUNCTION__);
+
          return FALSE;
       }
 
@@ -827,7 +914,8 @@ Hostinfo_GetOSName(uint32 outBufFullLen,  // IN: length of osNameFull buffer
       }
 
       if (nameLen + releaseLen + 1 > outBufLen) {
-         Warning("GuestInfoGetOSName: Error: buffer too small\n");
+         Warning("%s: Error: buffer too small\n", __FUNCTION__);
+
          return FALSE;
       }
 
@@ -837,14 +925,14 @@ Hostinfo_GetOSName(uint32 outBufFullLen,  // IN: length of osNameFull buffer
    if (Hostinfo_GetSystemBitness() == 64) {
       if (strlen(osName) + sizeof STR_OS_64BIT_SUFFIX > outBufLen) {
          Warning("%s: Error: buffer too small\n", __FUNCTION__);
+
          return FALSE;
       }
       Str_Strcat(osName, STR_OS_64BIT_SUFFIX, outBufLen);
    }
 
    /*
-    * Before returning, truncate
-    * the \n character at the end of the full name.
+    * Before returning, truncate the \n character at the end of the full name.
     */
 
    lastCharPos = strlen(osNameFull) - 1;
@@ -855,3 +943,1409 @@ Hostinfo_GetOSName(uint32 outBufFullLen,  // IN: length of osNameFull buffer
    return TRUE;
 }
 
+
+#if defined(VMX86_SERVER)
+/*
+ *----------------------------------------------------------------------
+ *
+ * HostinfoReadProc --
+ *
+ *      Depending on what string is passed to it, this function parses the
+ *      /proc/vmware/sched/ncpus node and returns the requested value.
+ *
+ * Results:
+ *      A postive value on success, -1 (0xFFFFFFFF) on failure.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static uint32
+HostinfoReadProc(const char *str)  // IN:
+{
+   /* XXX this should use sysinfo!! (bug 59849)
+    */
+   FILE *f;
+   char *line;
+   uint32 count;
+
+   ASSERT(!strcmp("logical", str) || !strcmp("cores", str) ||
+          !strcmp("packages", str)); 
+
+   ASSERT(!HostType_OSIsVMK()); // Don't use /proc/vmware
+
+   f = Posix_Fopen("/proc/vmware/sched/ncpus", "r");
+
+   if (f != NULL) {
+      while (StdIO_ReadNextLine(f, &line, 0, NULL) == StdIO_Success) {
+         if (strstr(line, str)) {
+            if (sscanf(line, "%d ", &count) == 1) {
+               free(line);
+               break;
+            }
+         }
+         free(line);
+      }
+      fclose(f);
+
+      if (count > 0) {
+         return count;
+      }
+   }
+
+   return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Hostinfo_HTDisabled --
+ *
+ *      Figure out if hyperthreading is enabled
+ *
+ * Results:
+ *      TRUE if hyperthreading is disabled, FALSE otherwise
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+Hostinfo_HTDisabled(void)
+{
+   static uint32 logical = 0, cores = 0;
+
+   if (HostType_OSIsVMK()) {
+      VMK_ReturnStatus status = VMKernel_HTEnabledCPU();
+      if (status != VMK_OK) {
+         return TRUE;
+      } else {
+         return FALSE;
+      }
+   }
+
+   if (logical == 0 && cores == 0) {
+      logical = HostinfoReadProc("logical");
+      cores = HostinfoReadProc("cores");
+      if (logical <= 0 || cores <= 0) {
+         logical = cores = 0;
+      }
+   }
+
+   return logical == cores;
+}
+#endif /*ifdef VMX86_SERVER*/
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_NumCPUs --
+ *
+ *      Get the number of logical CPUs on the host.  If the CPUs are
+ *      hyperthread-capable, this number may be larger than the number of
+ *      physical CPUs.  For example, if the host has four hyperthreaded
+ *      physical CPUs with 2 logical CPUs apiece, this function returns 8.
+ *
+ *      This function returns the number of CPUs that the host presents to
+ *      applications, which is what we want in the vast majority of cases.  We
+ *      would only ever care about the number of physical CPUs for licensing
+ *      purposes.
+ *
+ * Results:
+ *      On success, the number of CPUs (> 0) the host tells us we have.
+ *      On failure, 0xFFFFFFFF (-1).
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+uint32
+Hostinfo_NumCPUs(void)
+{
+#if defined(__APPLE__)
+   uint32 out;
+   size_t outSize = sizeof out;
+
+   /*
+    * Quoting sys/sysctl.h:
+    * "
+    * These are the support HW selectors for sysctlbyname.  Parameters that
+    * are byte counts or frequencies are 64 bit numbers. All other parameters
+    * are 32 bit numbers.
+    * ...
+    * hw.activecpu - The number of processors currently available for executing
+    *                threads. Use this number to determine the number threads
+    *                to create in SMP aware applications. This number can
+    *                change when power management modes are changed.
+    * "
+    *
+    * Apparently the only way to retrieve this info is by name, and I have
+    * verified the info changes when you dynamically switch a CPU
+    * offline/online. --hpreg
+    */
+
+   if (sysctlbyname("hw.activecpu", &out, &outSize, NULL, 0) == -1) {
+      return -1;
+   }
+
+   return out;
+#elif defined(__FreeBSD__)
+   uint32 out;
+   size_t outSize = sizeof out;
+
+#if __FreeBSD__version >= 500019
+   if (sysctlbyname("kern.smp.cpus", &out, &outSize, NULL, 0) == -1) {
+      return -1;
+   }
+#else
+   if (sysctlbyname("machdep.smp_cpus", &out, &outSize, NULL, 0) == -1) {
+      if (errno == ENOENT) {
+         out = 1;
+      } else {
+         return -1;
+      }
+   }
+#endif
+
+   return out;
+#else
+   static int count = 0;
+
+   if (count <= 0) {
+#if defined(VMX86_SERVER)
+      if (HostType_OSIsVMK()) {
+         VMK_ReturnStatus status = VMKernel_GetNumCPUsUsed(&count);
+
+         if (status != VMK_OK) {
+            count = 0;
+
+            return -1;
+         }
+      } else {
+         count = HostinfoReadProc("logical");
+
+         if (count <= 0) {
+            count = 0;
+
+            return -1;
+         }
+      }
+#else /* ifdef VMX86_SERVER */
+      FILE *f;
+      char *line;
+
+      f = Posix_Fopen("/proc/cpuinfo", "r");
+      if (f == NULL) { 
+        return -1;
+      }
+
+      while (StdIO_ReadNextLine(f, &line, 0, NULL) == StdIO_Success) {
+        if (strncmp(line, "processor", strlen("processor")) == 0) {
+           count++;
+        }
+        free(line);
+      }
+
+      fclose(f);
+
+      if (count == 0) {
+        return -1;
+      }
+#endif /* ifdef VMX86_SERVER */
+   }
+
+   return count;
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Hostinfo_OSIsSMP --
+ *
+ *      Host OS SMP capability.
+ *
+ * Results:
+ *      TRUE is host OS is SMP capable.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+Hostinfo_OSIsSMP(void)
+{
+   uint32 ncpu;
+
+#if defined(__APPLE__)
+   size_t ncpuSize = sizeof ncpu;
+
+   if (sysctlbyname("hw.ncpu", &ncpu, &ncpuSize, NULL, 0) == -1) {
+      return FALSE;
+   }
+
+#else
+   ncpu = Hostinfo_NumCPUs();
+
+   if (ncpu == 0xFFFFFFFF) {
+      return FALSE;
+   }
+#endif
+
+   return ncpu > 1 ? TRUE : FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_NameGet --
+ *
+ *      Return the fully qualified host name of the host.
+ *      Thread-safe. --hpreg
+ *
+ * Results:
+ *      The (memorized) name on success
+ *      NULL on failure
+ *
+ * Side effects:
+ *      A host name resolution can occur.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Unicode
+Hostinfo_NameGet(void)
+{
+   Unicode result;
+
+   static Atomic_Ptr state; /* Implicitly initialized to NULL. --hpreg */
+
+   result = Atomic_ReadPtr(&state);
+
+   if (UNLIKELY(result == NULL)) {
+      Unicode before;
+
+      result = Hostinfo_HostName();
+
+      before = Atomic_ReadIfEqualWritePtr(&state, NULL, result);
+
+      if (before) {
+         Unicode_Free(result);
+
+         result = before;
+      }
+   }
+
+   return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_GetUser --
+ *
+ *      Return current user name, or NULL if can't tell.
+ *      XXX Not thread-safe (somebody could do a setenv()). --hpreg
+ *
+ * Results:
+ *      User name.  Must be free()d by caller.
+ *
+ * Side effects:
+ *     No.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Unicode
+Hostinfo_GetUser(void)
+{
+   char buffer[BUFSIZ];
+   struct passwd pw;
+   struct passwd *ppw = &pw;
+   Unicode env = NULL;
+   Unicode name = NULL;
+
+   if ((Posix_Getpwuid_r(getuid(), &pw, buffer, sizeof buffer, &ppw) == 0) &&
+       (ppw != NULL)) {
+      if (ppw->pw_name) {
+         name = Unicode_Duplicate(ppw->pw_name);
+      }
+   }
+
+   if (!name) {
+      env = Posix_Getenv("USER");
+
+      if (env) {
+         name = Unicode_Duplicate(env);
+      }
+   }
+
+   return name;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HostinfoGetLoadAverage --
+ *
+ *      Returns system average load.
+ *
+ * Results:
+ *      TRUE on success, FALSE otherwise.
+ *
+ * Side effects:
+ *     None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HostinfoGetLoadAverage(float *avg0,  // IN/OUT:
+                       float *avg1,  // IN/OUT:
+                       float *avg2)  // IN/OUT:
+{
+   /* getloadavg(3) was introduced with glibc 2.2 */
+#if defined(GLIBC_VERSION_22) || defined(__APPLE__)
+   double avg[3];
+   int res;
+
+   res = getloadavg(avg, 3);
+   if (res < 3) {
+      NOT_TESTED_ONCE();
+      return FALSE;
+   }
+
+   if (avg0) {
+      *avg0 = (float) avg[0];
+   }
+   if (avg1) {
+      *avg1 = (float) avg[1];
+   }
+   if (avg2) {
+      *avg2 = (float) avg[2];
+   }
+
+   return TRUE;
+#else
+   /* 
+    * Not implemented. This function is currently only used in the vmx, so
+    * getloadavg is always available to us. If the linux tools ever need this,
+    * we can go back to having a look at the output of /proc/loadavg, but
+    * let's not do that now as long as it's not necessary.
+    */
+
+   NOT_IMPLEMENTED();
+
+   return FALSE;
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_GetLoadAverage --
+ *
+ *      Returns system average load * 100.
+ *
+ * Results:
+ *      TRUE/FALSE
+ *
+ * Side effects:
+ *     None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+Hostinfo_GetLoadAverage(uint32 *avg)  // IN/OUT:
+{
+   float avg0 = 0;
+
+   if (!HostinfoGetLoadAverage(&avg0, NULL, NULL)) {
+      return FALSE;
+   }
+
+   *avg = (uint32) 100 * avg0;
+
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_LogLoadAverage --
+ *
+ *      Logs system average load.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Hostinfo_LogLoadAverage(void)
+{
+   float avg0 = 0, avg1 = 0, avg2 = 0;
+
+   if (HostinfoGetLoadAverage(&avg0, &avg1, &avg2)) {
+      Log("LOADAVG: %.2f %.2f %.2f\n", avg0, avg1, avg2);
+   }
+}
+
+
+#if defined(__APPLE__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HostinfoMacAbsTimeNS --
+ *
+ *      Return the Mac OS absolute time.
+ *
+ * Results:
+ *      The absolute time in nanoseconds is returned. This time is documented
+ *      to NEVER go backwards.
+ *
+ * Side effects:
+ *     None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static inline VmTimeType
+HostinfoMacAbsTimeNS(void)
+{
+   VmTimeType raw;
+   mach_timebase_info_data_t *ptr;
+   static Atomic_Ptr atomic; /* Implicitly initialized to NULL. --mbellon */
+
+   /* Insure that the time base values are correct. */
+   ptr = (mach_timebase_info_data_t *) Atomic_ReadPtr(&atomic);
+
+   if (ptr == NULL) {
+      char *p;
+
+      p = Util_SafeMalloc(sizeof(mach_timebase_info_data_t));
+
+      mach_timebase_info((mach_timebase_info_data_t *) p);
+
+      if (Atomic_ReadIfEqualWritePtr(&atomic, NULL, p)) {
+         free(p);
+      }
+
+      ptr = (mach_timebase_info_data_t *) Atomic_ReadPtr(&atomic);
+   }
+
+   raw = mach_absolute_time();
+
+   if ((ptr->numer == 1) && (ptr->denom == 1)) {
+      /* The scaling values are unity, save some time/arithmetic */
+      return raw;
+   } else {
+      /* The scaling values are not unity. Prevent overflow when scaling */
+      return ((double) raw) * (((double) ptr->numer) / ((double) ptr->denom));
+   }
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HostinfoRawSystemTimerUS --
+ *
+ *      Obtain the raw system timer value.
+ *
+ * Results:
+ *      Relative time in microseconds or zero if a failure.
+ *
+ * Side effects:
+ *     None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+VmTimeType
+Hostinfo_RawSystemTimerUS(void)
+{
+#if defined(__APPLE__)
+   return HostinfoMacAbsTimeNS() / 1000ULL;
+#else
+#if defined(VMX86_SERVER)
+   if (HostType_OSIsPureVMK()) {
+      uint64 uptime;
+      VMK_ReturnStatus status;
+
+      status = VMKernel_GetUptimeUS(&uptime);
+      if (status != VMK_OK) {
+         Log("%s: failure!\n", __FUNCTION__);
+         return 0;  // A timer read failure - this is really bad!
+      }
+
+      return uptime;
+   } else {
+#endif /* ifdef VMX86_SERVER */
+      struct timeval tval;
+
+      /* Read the time from the operating system */
+      if (gettimeofday(&tval, NULL) != 0) {
+         Log("%s: failure!\n", __FUNCTION__);
+
+         return 0;  // A timer read failure - this is really bad!
+      }
+
+      /* Convert into microseconds */
+      return (((VmTimeType)tval.tv_sec) * 1000000 + tval.tv_usec);
+#if defined(VMX86_SERVER)
+   }
+#endif /* ifdef VMX86_SERVER */
+#endif /* ifdef __APPLE__ */
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_LogMemUsage --
+ *      Log system memory usage.
+ *
+ * Results:
+ *      System memory usage is logged.
+ *
+ * Side effects:
+ *      No.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Hostinfo_LogMemUsage(void)
+{
+   int fd = Posix_Open("/proc/self/statm", O_RDONLY);
+
+   if (fd != -1) {
+      size_t len;
+      char buf[64];
+
+      len = read(fd, buf, sizeof buf);
+      close(fd);
+
+      if (len != -1) {
+         int a[7] = { 0 };
+
+         buf[len < sizeof buf ? len : sizeof buf - 1] = '\0';
+
+         sscanf(buf, "%d %d %d %d %d %d %d",
+                &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]);
+
+         Log("RUSAGE size=%d resident=%d share=%d trs=%d lrs=%d drs=%d dt=%d\n",
+             a[0], a[1], a[2], a[3], a[4], a[5], a[6]);
+      }
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ *  Hostinfo_TouchBackDoor --
+ *
+ *      Access the backdoor. This is used to determine if we are 
+ *      running in a VM or on a physical host. On a physical host
+ *      this should generate a GP which we catch and thereby determine
+ *      that we are not in a VM. However some OSes do not handle the
+ *      GP correctly and the process continues running returning garbage.
+ *      In this case we check the EBX register which should be 
+ *      BDOOR_MAGIC if the IN was handled in a VM. Based on this we
+ *      return either TRUE or FALSE.
+ *
+ * Results:
+ *      TRUE if we succesfully accessed the backdoor, FALSE or segfault
+ *      if not.
+ *
+ * Side effects:
+ *     Exception if not in a VM. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+Hostinfo_TouchBackDoor(void)
+{
+   /*
+    * XXX: This can cause Apple's Crash Reporter to erroneously display
+    * a crash, even though the process has caught the SIGILL and handled
+    * it.
+    *
+    * It's also annoying in gdb, so we'll turn it off in devel builds.
+    */
+
+#if !defined(__APPLE__) && !defined(VMX86_DEVEL)
+   uint32 eax;
+   uint32 ebx;
+   uint32 ecx;
+
+   __asm__ __volatile__(
+#   if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
+      "xchgl %%ebx, %1" "\n\t"
+      "inl %%dx, %%eax" "\n\t"
+      "xchgl %%ebx, %1"
+      : "=a" (eax),
+        "=&rm" (ebx),
+#   else
+      "inl %%dx, %%eax"
+      : "=a" (eax),
+        "=b" (ebx),
+#   endif
+        "=c" (ecx)
+      :        "0" (BDOOR_MAGIC),
+        "1" (~BDOOR_MAGIC),
+        "2" (BDOOR_CMD_GETVERSION),
+        "d" (BDOOR_PORT)
+   );
+   if (ebx == BDOOR_MAGIC) {
+      return TRUE;
+   }
+#endif
+   return FALSE;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Hostinfo_ResetProcessState --
+ *
+ *      Clean up signal handlers and file descriptors before an exec().
+ *      Fds which need to be kept open can be passed as an array.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Hostinfo_ResetProcessState(const int *keepFds, // IN:
+                           size_t numKeepFds)  // IN:
+{
+   int s, fd;
+   struct sigaction sa;
+   struct rlimit rlim;
+#ifdef __linux__
+   int err;
+   uid_t euid;
+#endif
+
+   /*
+    * Disable itimers before resetting the signal handlers.
+    * Otherwise, the process may still receive timer signals:
+    * SIGALRM, SIGVTARLM, or SIGPROF.
+    */
+
+   struct itimerval it;
+   it.it_value.tv_sec = it.it_value.tv_usec = 0;
+   it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
+   setitimer(ITIMER_REAL, &it, NULL);
+   setitimer(ITIMER_VIRTUAL, &it, NULL);
+   setitimer(ITIMER_PROF, &it, NULL);
+
+   for (s = 1; s <= NSIG; s++) {
+      sa.sa_handler = SIG_DFL;
+      sigfillset(&sa.sa_mask);
+      sa.sa_flags = SA_RESTART;
+      sigaction(s, &sa, NULL);
+   }
+
+   for (fd = (int) sysconf(_SC_OPEN_MAX) - 1; fd > STDERR_FILENO; fd--) {
+      size_t i;
+
+      for (i = 0; i < numKeepFds; i++) {
+         if (fd == keepFds[i]) {
+            break;
+         }
+      }
+      if (i == numKeepFds) {
+         (void) close(fd);
+      }
+   }
+
+   if (getrlimit(RLIMIT_AS, &rlim) == 0) {
+      rlim.rlim_cur = rlim.rlim_max;
+      setrlimit(RLIMIT_AS, &rlim);
+   }
+
+#ifdef __linux__
+   /*
+    * Drop iopl to its default value.
+    */
+   euid = Id_GetEUid();
+   /* At this point, _unless we are running as root_, we shouldn't have root
+      privileges --hpreg */
+   ASSERT(euid != 0 || getuid() == 0);
+   Id_SetEUid(0);
+   err = iopl(0);
+   Id_SetEUid(euid);
+   ASSERT_NOT_IMPLEMENTED(err == 0);
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_Daemonize --
+ *
+ *      Cross-platform daemon(3)-like wrapper.
+ *
+ *      Restarts the current process as a daemon, given the path to the
+ *      process (usually from Hostinfo_GetModulePath).  This means:
+ *
+ *         * You're detached from your parent.  (Your parent doesn't
+ *           need to wait for you to exit.)
+ *         * Your process no longer has a controlling terminal or
+ *           process group.
+ *         * Your stdin/stdout/stderr fds are redirected to /dev/null. All
+ *           other descriptors, except for the ones that are passed in the
+ *           parameter keepFds, are closed.
+ *         * Your signal handlers are reset to SIG_DFL in the daemonized
+ *           process, and all the signals are unblocked.
+ *         * Your main() function is called with the specified NULL-terminated
+ *           argument list.
+ *
+ *      (Don't forget that the first string in args is argv[0] -- the
+ *      name of the process).
+ *
+ *      Unless 'flags' contains HOSTINFO_DAEMONIZE_NOCHDIR, then the
+ *      current directory of the daemon process is set to "/".
+ *
+ *      Unless 'flags' contains HOSTINFO_DAEMONIZE_NOCLOSE, then all stdio
+ *      file descriptors of the daemon process are redirected to /dev/null.
+ *      This is true even if the stdio descriptors are included in keepFds,
+ *      i.e. the list of fds to be kept open.
+ *
+ *      If 'flags' contains HOSTINFO_DAEMONIZE_EXIT, then upon successful
+ *      launch of the daemon, the original process will exit.
+ *
+ *      If pidPath is non-NULL, then upon success, writes the PID
+ *      (as a US-ASCII string followed by a newline) of the daemon
+ *      process to that path.
+ *
+ * Results:
+ *      FALSE if the process could not be daemonized.  Err_Errno() contains
+ *      the error on failure.
+ *      TRUE if 'flags' does not contain HOSTINFO_DAEMONIZE_EXIT and
+ *      the process was daemonized.
+ *      Otherwise, if the process was daemonized, this function does
+ *      not return, and flow continues from your own main() function.
+ *
+ * Side effects:
+ *      The current process is restarted with the given arguments.
+ *      The process state is reset (see Hostinfo_ResetProcessState).
+ *      A new session is created (so the process has no controlling terminal).
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+Hostinfo_Daemonize(const char *path,             // IN: NUL-terminated UTF-8
+                                                 // path to exec
+                   char * const *args,           // IN: NULL-terminated UTF-8
+                                                 // argv list
+                   HostinfoDaemonizeFlags flags, // IN: flags
+                   const char *pidPath,          // IN/OPT: NUL-terminated
+                                                 // UTF-8 path to write PID
+                   const int *keepFds,           // IN/OPT: array of fds to be
+                                                 // kept open
+                   size_t numKeepFds)            // IN: number of fds in
+                                                 // keepFds
+{
+   /*
+    * We use the double-fork method to make a background process whose
+    * parent is init instead of the original process.
+    *
+    * We do this instead of calling daemon(), because daemon() is
+    * deprecated on Mac OS 10.5 hosts, and calling it causes a compiler
+    * warning.
+    *
+    * We must exec() after forking, because Mac OS library frameworks
+    * depend on internal Mach ports, which are not correctly propagated
+    * across fork calls.  exec'ing reinitializes the frameworks, which
+    * causes them to reopen their Mach ports.
+    */
+
+   int childPid;
+   int pipeFds[2] = { -1, -1 };
+   uint32 err = EINVAL;
+   char *pathLocalEncoding = NULL;
+   char *pidPathLocalEncoding = NULL;
+   char **argsLocalEncoding = NULL;
+   int *tempFds = NULL;
+   sigset_t sig;
+
+   ASSERT_ON_COMPILE(sizeof (errno) <= sizeof err);
+   ASSERT(args);
+   ASSERT(path);
+   ASSERT(numKeepFds == 0 || keepFds);
+
+   if (pipe(pipeFds) == -1) {
+      err = Err_Errno();
+      Warning("%s: Couldn't create pipe, error %u.\n", __FUNCTION__, err);
+      pipeFds[0] = pipeFds[1] = -1;
+      goto cleanup;
+   }
+
+   numKeepFds++;
+   tempFds = malloc(sizeof tempFds[0] * numKeepFds);
+   if (!tempFds) {
+      err = Err_Errno();
+      Warning("%s: Couldn't allocate memory, error %u.\n", __FUNCTION__, err);
+      goto cleanup;
+   }
+   tempFds[0] = pipeFds[1];
+   if (keepFds) {
+      memcpy(tempFds + 1, keepFds, sizeof tempFds[0] * (numKeepFds - 1));
+   }
+
+   if (fcntl(pipeFds[1], F_SETFD, 1) == -1) {
+      err = Err_Errno();
+      Warning("%s: Couldn't set close-on-exec for fd %d, error %u.\n",
+              __FUNCTION__, pipeFds[1], err);
+      goto cleanup;
+   }
+
+   /* Convert the strings from UTF-8 before we fork. */
+   pathLocalEncoding = Unicode_GetAllocBytes(path, STRING_ENCODING_DEFAULT);
+   if (!pathLocalEncoding) {
+      Warning("%s: Couldn't convert path [%s] to default encoding.\n",
+              __FUNCTION__, path);
+      goto cleanup;
+   }
+
+   if (pidPath) {
+      pidPathLocalEncoding = Unicode_GetAllocBytes(pidPath,
+                                                   STRING_ENCODING_DEFAULT);
+
+      if (!pidPathLocalEncoding) {
+         Warning("%s: Couldn't convert path [%s] to default encoding.\n",
+                 __FUNCTION__, pidPath);
+         goto cleanup;
+      }
+   }
+
+   argsLocalEncoding = Unicode_GetAllocList(args, STRING_ENCODING_DEFAULT, -1);
+   if (!argsLocalEncoding) {
+      Warning("%s: Couldn't convert arguments to default encoding.\n",
+              __FUNCTION__);
+      goto cleanup;
+   }
+
+   childPid = fork();
+
+   switch (childPid) {
+   case -1:
+      err = Err_Errno();
+      Warning("%s: Couldn't fork first child, error %u.\n", __FUNCTION__, err);
+      goto cleanup;
+   case 0:
+      /* We're the first child.  Continue on. */
+      break;
+   default:
+      {
+         /* We're the original process.  Check if the first child exited. */
+         int status;
+
+         close(pipeFds[1]);
+         waitpid(childPid, &status, 0);
+         if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS) {
+            Warning("%s: Child %d exited with error %d.\n",
+                    __FUNCTION__, childPid, WEXITSTATUS(status));
+            goto cleanup;
+         } else if (WIFSIGNALED(status)) {
+            Warning("%s: Child %d exited with signal %d.\n",
+                    __FUNCTION__, childPid, WTERMSIG(status));
+            goto cleanup;
+         }
+
+         /*
+          * Check if the second child exec'ed successfully.  If it had
+          * an error, it will write a uint32 errno to this pipe before
+          * exiting.  Otherwise, its end of the pipe will be closed on
+          * exec and this call will fail as expected.
+          * The assumption is that we don't get a partial read. In case,
+          * it did happen, we can detect it by the number of bytes read.
+          */
+
+         while (TRUE) {
+            int res = read(pipeFds[0], &err, sizeof err);
+
+            if (res > 0) {
+               Warning("%s: Child could not exec %s, read %d, error %u.\n",
+                       __FUNCTION__, path, res, err);
+               goto cleanup;
+            } else if (res == -1 && errno == EINTR) {
+               continue;
+            }
+            break;
+         }
+
+         err = 0;
+         goto cleanup;
+      }
+   }
+
+   /*
+    * Close all fds except for the write end of the error pipe (which
+    * we've already set to close on successful exec), and the ones requested by
+    * the caller. Also reset the signal mask to unblock all signals. fork()
+    * clears pending signals.
+    */
+
+   Hostinfo_ResetProcessState(tempFds, numKeepFds);
+   free(tempFds);
+   tempFds = NULL;
+   sigfillset(&sig);
+   sigprocmask(SIG_UNBLOCK, &sig, NULL);
+
+   if (!(flags & HOSTINFO_DAEMONIZE_NOCLOSE) && setsid() == -1) {
+      Warning("%s: Couldn't create new session, error %d.\n",
+              __FUNCTION__, Err_Errno());
+
+      _exit(EXIT_FAILURE);
+   }
+
+   switch (fork()) {
+   case -1:
+      {
+         Warning("%s: Couldn't fork second child, error %d.\n",
+                 __FUNCTION__, Err_Errno());
+
+         _exit(EXIT_FAILURE);
+      }
+   case 0:
+      // We're the second child.  Continue on.
+      break;
+   default:
+      /*
+       * We're the first child.  We don't need to exist any more.
+       *
+       * Exiting here causes the second child to be reparented to the
+       * init process, so the original process doesn't need to wait
+       * for the child we forked off.
+       */
+
+      _exit(EXIT_SUCCESS);
+   }
+
+   /*
+    * We can't use our i18n wrappers for file manipulation at this
+    * point, since we've forked; internal library mutexes might be
+    * invalid.
+    */
+
+   if (!(flags & HOSTINFO_DAEMONIZE_NOCHDIR) && chdir("/") == -1) {
+      uint32 err = Err_Errno();
+
+      Warning("%s: Couldn't chdir to /, error %u.\n", __FUNCTION__, err);
+
+      /* Let the original process know we failed to chdir. */
+      if (write(pipeFds[1], &err, sizeof err) == -1) {
+         Warning("%s: Couldn't write to parent pipe: %u, original error: %u.\n",
+                 __FUNCTION__, Err_Errno(), err);
+      }
+      _exit(EXIT_FAILURE);
+   }
+
+   if (!(flags & HOSTINFO_DAEMONIZE_NOCLOSE)) {
+      int fd;
+
+      fd = open(_PATH_DEVNULL, O_RDONLY);
+      if (fd != -1) {
+         dup2(fd, STDIN_FILENO);
+         close(fd);
+      }
+
+      fd = open(_PATH_DEVNULL, O_WRONLY);
+      if (fd != -1) {
+         dup2(fd, STDOUT_FILENO);
+         dup2(fd, STDERR_FILENO);
+         close(fd);
+      }
+   }
+
+   if (pidPath) {
+      int64 pid;
+      char pidString[32];
+      int pidStringLen;
+      int pidPathFd;
+
+      ASSERT_ON_COMPILE(sizeof (pid_t) <= sizeof pid);
+      ASSERT(pidPathLocalEncoding);
+
+      /* See above comment about how we can't use our i18n wrappers here. */
+      pidPathFd = open(pidPathLocalEncoding, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+
+      if (pidPathFd == -1) {
+         err = Err_Errno();
+         Warning("%s: Couldn't open PID path [%s], error %d.\n",
+                 __FUNCTION__, pidPath, err);
+
+         if (write(pipeFds[1], &err, sizeof err) == -1) {
+            Warning("%s: Couldn't write to parent pipe: %u, original "
+                    "error: %u.\n", __FUNCTION__, Err_Errno(), err);
+         }
+         _exit(EXIT_FAILURE);
+      }
+
+      pid = getpid();
+      pidStringLen = Str_Sprintf(pidString, sizeof pidString,
+                                 "%"FMT64"d\n", pid);
+      if (pidStringLen <= 0) {
+         err = EINVAL;
+
+         if (write(pipeFds[1], &err, sizeof err) == -1) {
+            Warning("%s: Couldn't write to parent pipe: %u, original "
+                    "error: %u.\n", __FUNCTION__, Err_Errno(), err);
+         }
+         _exit(EXIT_FAILURE);
+      }
+
+      if (write(pidPathFd, pidString, pidStringLen) != pidStringLen) {
+         err = Err_Errno();
+         Warning("%s: Couldn't write PID to path [%s], error %d.\n",
+                 __FUNCTION__, pidPath, err);
+
+         if (write(pipeFds[1], &err, sizeof err) == -1) {
+            Warning("%s: Couldn't write to parent pipe: %u, original "
+                    "error: %u.\n", __FUNCTION__, Err_Errno(), err);
+         }
+         _exit(EXIT_FAILURE);
+      }
+
+      close(pidPathFd);
+   }
+
+   if (execv(pathLocalEncoding, argsLocalEncoding) == -1) {
+      err = Err_Errno();
+      Warning("%s: Couldn't exec %s, error %d.\n", __FUNCTION__, path, err);
+
+      /* Let the original process know we failed to exec. */
+      if (write(pipeFds[1], &err, sizeof err) == -1) {
+         Warning("Couldn't write to parent pipe: %u, original error: %u.\n",
+                 Err_Errno(), err);
+      }
+      _exit(EXIT_FAILURE);
+   }
+
+   NOT_REACHED();
+
+  cleanup:
+   free(tempFds);
+
+   if (pipeFds[0] != -1) {
+      close(pipeFds[0]);
+   }
+   if (pipeFds[1] != -1) {
+      close(pipeFds[1]);
+   }
+   Util_FreeStringList(argsLocalEncoding, -1);
+   free(pidPathLocalEncoding);
+   free(pathLocalEncoding);
+
+   if (err == 0) {
+      if (flags & HOSTINFO_DAEMONIZE_EXIT) {
+         _exit(EXIT_SUCCESS);
+      }
+   } else {
+      Err_SetErrno(err);
+
+      if (pidPath) {
+         Posix_Unlink(pidPath);
+      }
+   }
+
+   return (err == 0);
+}
+
+
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
+/*
+ *----------------------------------------------------------------------
+ *
+ * HostinfoGetCpuInfo --
+ *
+ *      Get some attribute from /proc/cpuinfo for a given CPU
+ *
+ * Results:
+ *      On success: Allocated, NUL-terminated attribute string.
+ *      On failure: NULL.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+HostinfoGetCpuInfo(int nCpu,    // IN:
+                   char *name)  // IN:
+{
+   FILE *f;
+   char *line;
+   int cpu = 0;
+   char *value = NULL;
+
+   f = Posix_Fopen("/proc/cpuinfo", "r");
+
+   if (f == NULL) { 
+      Warning(LGPFX" %s: Unable to open /proc/cpuinfo\n", __FUNCTION__);
+
+      return NULL;
+   }
+      
+   while (cpu <= nCpu && 
+          StdIO_ReadNextLine(f, &line, 0, NULL) == StdIO_Success) {
+      char *s;
+      char *e;
+
+      if ((s = strstr(line, name)) &&
+          (s = strchr(s, ':'))) {
+         s++;
+         e = s + strlen(s);
+
+         /* Skip leading and trailing while spaces */
+         for (; s < e && isspace(*s); s++);
+         for (; s < e && isspace(e[-1]); e--);
+         *e = 0;
+         
+         /* Free previous value */
+         free(value);
+         value = strdup(s);
+         ASSERT_MEM_ALLOC(value);
+         
+         cpu++;
+      }
+      free(line);
+   }     
+
+   fclose(f);
+
+   return value; 
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_GetRatedCpuMhz --
+ *
+ *      Get the rated CPU speed of a given processor. 
+ *      Return value is in MHz.
+ *
+ * Results:
+ *      TRUE on success, FALSE on failure
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+Hostinfo_GetRatedCpuMhz(int32 cpuNumber,  // IN:
+                        uint32 *mHz)      // OUT:
+{
+#if defined(__APPLE__) || defined(__FreeBSD__)
+
+#  if defined(__APPLE__)
+#     define CPUMHZ_SYSCTL_NAME "hw.cpufrequency_max"
+#  elif __FreeBSD__version >= 50011
+#     define CPUMHZ_SYSCTL_NAME "hw.clockrate"
+#  endif
+
+#  if defined(CPUMHZ_SYSCTL_NAME)
+   uint32 hz;
+   size_t hzSize = sizeof hz;
+
+   /* 'cpuNumber' is ignored: Intel Macs are always perfectly symetric. */
+
+   if (sysctlbyname(CPUMHZ_SYSCTL_NAME, &hz, &hzSize, NULL, 0) == -1) {
+      return FALSE;
+   }
+
+   *mHz = hz / 1000000;
+
+   return TRUE;
+#  else
+   return FALSE;
+#  endif
+#else
+   float fMhz = 0;
+   char *readVal = HostinfoGetCpuInfo(cpuNumber, "cpu MHz");
+   
+   if (readVal == NULL) {
+      return FALSE;
+   }
+   
+   if (sscanf(readVal, "%f", &fMhz) == 1) {
+      *mHz = (unsigned int)(fMhz + 0.5);
+   }
+   free(readVal);
+
+   return TRUE;
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_GetCpuDescription --
+ *
+ *      Get the descriptive name associated with a given CPU.
+ *
+ * Results:
+ *      On success: Allocated, NUL-terminated string.
+ *      On failure: NULL.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char *
+Hostinfo_GetCpuDescription(uint32 cpuNumber)  // IN:
+{
+#if defined(__APPLE__) || defined(__FreeBSD__)
+#  if defined(__APPLE__)
+#     define CPUDESC_SYSCTL_NAME "machdep.cpu.brand_string"
+#  else
+#     define CPUDESC_SYSCTL_NAME "hw.model"
+#  endif
+
+   char *desc;
+   size_t descSize;
+
+   /* 'cpuNumber' is ignored: Intel Macs are always perfectly symetric. */
+
+   if (sysctlbyname(CPUDESC_SYSCTL_NAME, NULL, &descSize, NULL, 0) == -1) {
+      return NULL;
+   }
+
+   desc = malloc(descSize);
+   if (!desc) {
+      return NULL;
+   }
+
+   if (sysctlbyname(CPUDESC_SYSCTL_NAME, desc, &descSize, NULL, 0) == -1) {
+      free(desc);
+
+      return NULL;
+   }
+
+   return desc;
+#else
+#ifdef VMX86_SERVER
+   if (HostType_OSIsVMK()) {
+      char mName[48];
+
+      /* VMKernel treats mName as an in/out parameter so terminate it. */
+      mName[0] = '\0';
+      if (VMKernel_GetCPUModelName(mName, cpuNumber,
+                                   sizeof(mName)) == VMK_OK) {
+        mName[sizeof(mName) - 1] = '\0';
+
+         return strdup(mName);
+      }
+
+      return NULL;
+   }
+#endif
+
+   return HostinfoGetCpuInfo(cpuNumber, "model name");
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Hostinfo_Execute --
+ *
+ *      Start program COMMAND.  If WAIT is TRUE, wait for program
+ *     to complete and return exit status.
+ *
+ * Results:
+ *      Exit status of COMMAND.
+ *
+ * Side effects:
+ *      Run a separate program.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Hostinfo_Execute(const char *command,  // IN:
+                char * const *args,   // IN:
+                Bool wait)            // IN:
+{
+   int pid;
+   int status;
+
+   if (command == NULL) {
+      return 1;
+   }
+
+   pid = fork();
+
+   if (pid == -1) {
+      return -1;
+   }
+
+   if (pid == 0) {
+      Hostinfo_ResetProcessState(NULL, 0);
+      Posix_Execvp(command, args);
+      exit(127);
+   }
+
+   if (wait) {
+      for (;;) {
+        if (waitpid(pid, &status, 0) == -1) {
+           if (errno == ECHILD) {
+              return 0;        // This sucks.  We really don't know.
+           }
+           if (errno != EINTR) {
+              return -1;
+           }
+        } else {
+           return status;
+        }
+      }
+   } else {
+      return 0;
+   }
+}
index 2b1816047245ca61664bdbec6a7228f3e4a8ff61..f1175cb8a280eb3ce42bd84a5811b7a1c5006d1a 100644 (file)
@@ -273,3 +273,161 @@ NetUtil_GetPrimaryNic(void)
 abort:
    return nicEntry;
 }
+
+
+#if defined(linux)
+#   ifdef DUMMY_NETUTIL
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * NetUtil_GetIfIndex (dummy version) --
+ *
+ *      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
+{
+   NetUtilIfTableEntry *iterator;
+   int ifIndex = -1;
+
+   ASSERT(netUtilIfTable != NULL);
+
+   for (iterator = netUtilIfTable; iterator->ifName; iterator++) {
+      if (strcmp(iterator->ifName, ifName) == 0) {
+         ifIndex = iterator->ifIndex;
+         break;
+      }
+   }
+
+   return ifIndex;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * NetUtil_GetIfName (dummy version) --
+ *
+ *      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
+{
+   NetUtilIfTableEntry *iterator;
+   char *ifName = NULL;
+
+   ASSERT(netUtilIfTable != NULL);
+
+   for (iterator = netUtilIfTable; iterator->ifName; iterator++) {
+      if (iterator->ifIndex == ifIndex) {
+         ifName = Util_SafeStrdup(iterator->ifName);
+         break;
+      }
+   }
+
+   return ifName;
+}
+
+
+#   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
+
+#endif // if defined(linux)
index 14087255104235db604d2a7cef3730dde4cec466..d00ff7fc76a2c896ba0a011c0ee7a544aa25433a 100644 (file)
@@ -95,8 +95,9 @@ Printer_GetDefault(void)
 
    /* Make sure function has been loaded. */
    if (!getDefaultPrinterFunc) {
-      Log("Printer_GetDefault: DLL not loaded\n");
+      Log("%s: DLL not loaded\n", __FUNCTION__);
       ASSERT(FALSE);
+
       return NULL;
    }
 
@@ -104,27 +105,31 @@ Printer_GetDefault(void)
    success = getDefaultPrinterFunc(printerName, &bufSize);
    error = Err_Errno();
    if (success) {
-      Log("Printer_GetDefault: Didn't fail with zero buffer\n");
+      Log("%s: Didn't fail with zero buffer\n", __FUNCTION__);
+
       return NULL;
    }
 
    if (error != ERROR_INSUFFICIENT_BUFFER) {
-      Log("Printer_GetDefault: Unexpected failure %d: %s\n",
-          error, Err_Errno2String(error));
+      Log("%s: Unexpected failure %d: %s\n", error,
+          __FUNCTION__, Err_Errno2String(error));
+
       return NULL;
    }
 
    printerName = malloc(bufSize);
    if (!printerName) {
-      Log("Printer_GetDefault: Memory allocation failure\n");
+      Log("%s: Memory allocation failure\n", __FUNCTION__);
+
       return NULL;
    }
 
    success = getDefaultPrinterFunc(printerName, &bufSize);
    if (!success) {
       error = Err_Errno();
-      Log("Printer_GetDefault: Failed to get default printer\n");
+      Log("%s: Failed to get default printer\n", __FUNCTION__);
       free(printerName);
+
       return NULL;
    }
 
@@ -164,18 +169,21 @@ Printer_SetDefault(char const *printerName) // IN
 
    /* Make sure function has been loaded. */
    if (!setDefaultPrinterFunc) {
-      Log("Printer_SetDefault: DLL not loaded\n");
+      Log("%s: DLL not loaded\n", __FUNCTION__);
       ASSERT(FALSE);
+
       return FALSE;
    }
 
    /*
     * Attempt to set the default printer.
     */
+
    if (!setDefaultPrinterFunc(printerName)) {
       error = Err_Errno();
-      Log("Printer_SetDefault: Unable to SetDefaultPrinter %d: %s\n",
+      Log("%s: Unable to SetDefaultPrinter %d: %s\n", __FUNCTION__,
           error, Err_Errno2String(error));
+
       return FALSE;
    }
 
@@ -223,7 +231,7 @@ Printer_AddConnection(char *printerName, // IN:  Name of printer to add
 
    /* Make sure function has been loaded. */
    if (!addPrinterConnectionFunc) {
-      Log("Printer_AddConnection: DLL not loaded\n");
+      Log("%s: DLL not loaded\n", __FUNCTION__);
       ASSERT(FALSE);
       return FALSE;
    }
@@ -231,16 +239,18 @@ Printer_AddConnection(char *printerName, // IN:  Name of printer to add
    /* Try to add the printer. */
    if (!addPrinterConnectionFunc((LPSTR)printerName)) {
       error = Err_Errno();
-      Log("Printer_AddConnection: Failed to add printer %s : %d %s\n",
+      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
 }
@@ -278,16 +288,17 @@ Printer_Init(void)
    winspoolDll = Win32U_LoadLibrary("Winspool.drv");
    if (!winspoolDll) {
       error = Err_Errno();
-      Log("Printer_Init: Failed to load Winspool.drv  %d: %s\n",
+      Log("%s: Failed to load Winspool.drv  %d: %s\n", __FUNCTION__,
           error, Err_Errno2String(error));
 
-      Log("Printer_Init: Trying to load Winspool as Winspool.dll...\n");
+      Log("%s: Trying to load Winspool as Winspool.dll...\n", __FUNCTION__);
       winspoolDll = Win32U_LoadLibrary("Winspool");
       if (!winspoolDll) {
          error = Err_Errno();
-         Log("Printer_Init: Failed to load Winspool.dll  %d: %s\n",
+         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;
       }
    }
@@ -297,7 +308,7 @@ Printer_Init(void)
                                                                  "GetDefaultPrinterA");
    if (!getDefaultPrinterFunc) {
       error = Err_Errno();
-      Log("Printer_Init: Failed to load GetDefaultPrinter %d: %s\n",
+      Log("%s: Failed to load GetDefaultPrinter %d: %s\n", __FUNCTION__,
           error, Err_Errno2String(error));
       goto error;
    }
@@ -306,7 +317,7 @@ Printer_Init(void)
                                                                  "SetDefaultPrinterA");
    if (!setDefaultPrinterFunc) {
       error = Err_Errno();
-      Log("Printer_Init: Failed to load SetDefaultPrinter %d: %s\n",
+      Log("%s: Failed to load SetDefaultPrinter %d: %s\n", __FUNCTION__,
           error, Err_Errno2String(error));
       goto error;
    }
@@ -315,7 +326,7 @@ Printer_Init(void)
                                                              "AddPrinterConnectionA");
    if (!addPrinterConnectionFunc) {
       error = Err_Errno();
-      Log("Printer_Init: Failed to load AddPrinterConnection %d: %s\n",
+      Log("%s: Failed to load AddPrinterConnection %d: %s\n", __FUNCTION__,
           error, Err_Errno2String(error));
       goto error;
    }
@@ -359,7 +370,8 @@ Printer_Cleanup(void)
    DWORD error;
 
    if (!winspoolDll) {
-      Log("Printer_Cleanup: Printer library not loaded.\n");
+      Log("%s: Printer library not loaded.\n", __FUNCTION__);
+
       return FALSE;
    }
 
@@ -369,13 +381,15 @@ Printer_Cleanup(void)
 
    if (!FreeLibrary(winspoolDll)) {
       error = Err_Errno();
-      Log("Printer_Cleanup: Failed to FreeLibrary %d: %s\n",
+      Log("%s: Failed to FreeLibrary %d: %s\n", __FUNCTION__,
           error, Err_Errno2String(error));
       winspoolDll = NULL;
+
       return FALSE;
    }
 
    winspoolDll = NULL;
+
    return TRUE;
 
 #else
index 880a7254daba72f417e89100b2bd5400e169b229..a5e47465c87bde2505e35ccea4f78fafc82e7d57 100644 (file)
@@ -78,11 +78,11 @@ static const uint8 byte_masks_8bgr[9][3] = {
  */
 
 static void RasterConvert15to16(uint8 *tof, uint32 line_increment,
-                               uint8 *src, uint32 src_increment,
+                               const uint8 *src, uint32 src_increment,
                                uint32 src_x, uint32 src_y,
                                uint32 x, uint32 y, uint32 w, uint32 h);
 static void RasterConvertShortTo24(uint8 *tof, uint32 line_increment,
-                                  uint8 *src, uint32 src_increment,
+                                  const uint8 *src, uint32 src_increment,
                                   uint32 src_x, uint32 src_y,
                                   uint32 x, uint32 y, uint32 w, uint32 h,
                                   uint32 redMask, uint32 greenMask,
@@ -91,7 +91,7 @@ static void RasterConvertShortTo24(uint8 *tof, uint32 line_increment,
                                   uint32 greenShift1, uint32 greenShift2,
                                   uint32 blueShift1, uint32 blueShift2);
 static void RasterConvertShortTo32(uint8 *tof, uint32 line_increment,
-                                  uint8 *src, uint32 src_increment,
+                                  const uint8 *src, uint32 src_increment,
                                   uint32 src_x, uint32 src_y,
                                   uint32 x, uint32 y, uint32 w, uint32 h,
                                   uint32 redMask, uint32 greenMask,
@@ -100,11 +100,11 @@ static void RasterConvertShortTo32(uint8 *tof, uint32 line_increment,
                                   uint32 greenShift1, uint32 greenShift2,
                                   uint32 blueShift1, uint32 blueShift2);
 static void RasterConvert16to15(uint8 *tof, uint32 line_increment,
-                               uint8 *src, uint32 src_increment,
+                               const uint8 *src, uint32 src_increment,
                                uint32 src_x, uint32 src_y,
                                uint32 x, uint32 y, uint32 w, uint32 h);
 static void RasterConvert24toShort(uint8 *tof, uint32 line_increment,
-                                  uint8 *src, uint32 src_increment,
+                                  const uint8 *src, uint32 src_increment,
                                   uint32 src_x, uint32 src_y,
                                   uint32 x, uint32 y, uint32 w, uint32 h,
                                   uint32 redMask, uint32 greenMask,
@@ -112,11 +112,11 @@ static void RasterConvert24toShort(uint8 *tof, uint32 line_increment,
                                   uint32 redShift, uint32 greenShift,
                                   uint32 blueShift);
 static void RasterConvert24to32(uint8 *tof, uint32 line_increment,
-                               uint8 *src, uint32 src_increment,
+                               const uint8 *src, uint32 src_increment,
                                uint32 src_x, uint32 src_y,
                                uint32 x, uint32 y, uint32 w, uint32 h);
 static void RasterConvert32toShort(uint8 *tof, uint32 line_increment,
-                                  uint8 *src, uint32 src_increment,
+                                  const uint8 *src, uint32 src_increment,
                                   uint32 src_x, uint32 src_y,
                                   uint32 x, uint32 y, uint32 w, uint32 h,
                                   uint32 redMask, uint32 greenMask,
@@ -124,12 +124,12 @@ static void RasterConvert32toShort(uint8 *tof, uint32 line_increment,
                                   uint32 redShift, uint32 greenShift,
                                   uint32 blueShift);
 static void RasterConvert32to24(uint8 *tof, uint32 line_increment,
-                               uint8 *src, uint32 src_increment,
+                               const uint8 *src, uint32 src_increment,
                                uint32 src_x, uint32 src_y,
                                uint32 x, uint32 y, uint32 w, uint32 h);
 static void RasterConvertIndextoShort(uint8 *tof, uint32 line_increment,
-                                     uint8 *src, uint32 src_increment,
-                                     uint32 *pixels,
+                                     const uint8 *src, uint32 src_increment,
+                                     const uint32 *pixels,
                                      uint32 src_x, uint32 src_y,
                                      uint32 x, uint32 y, uint32 w, uint32 h,
                                      uint32 redMask, uint32 greenMask,
@@ -137,36 +137,37 @@ static void RasterConvertIndextoShort(uint8 *tof, uint32 line_increment,
                                      uint32 redShift, uint32 greenShift,
                                      uint32 blueShift);
 static void RasterConvertIndexto24(uint8 *tof, uint32 line_increment,
-                                  uint8 *src, uint32 src_increment,
-                                  uint32 *pixels,
+                                  const uint8 *src, uint32 src_increment,
+                                  const uint32 *pixels,
                                   uint32 src_x, uint32 src_y,
                                   uint32 x, uint32 y, uint32 w, uint32 h);
 static void RasterConvertIndexto32(uint8 *tof, uint32 line_increment,
-                                  uint8 *src, uint32 src_increment,
-                                  uint32 *pixels,
+                                  const uint8 *src, uint32 src_increment,
+                                  const uint32 *pixels,
                                   uint32 src_x, uint32 src_y,
                                   uint32 x, uint32 y, uint32 w, uint32 h);
 
 static void RasterConvert32to8(uint8 *tof, uint32 line_increment,
-                              uint8 *src, uint32 src_increment,
+                              const uint8 *src, uint32 src_increment,
                               uint32 src_x, uint32 src_y,
                               uint32 x, uint32 y, uint32 w, uint32 h,
                               uint32 redMask, uint32 greenMask, uint32 blueMask,
                               uint32 redShift, uint32 greenShift, uint32 blueShift);
 static void RasterConvert24to8(uint8 *tof, uint32 line_increment,
-                              uint8 *src, uint32 src_increment,
+                              const uint8 *src, uint32 src_increment,
                               uint32 src_x, uint32 src_y,
                               uint32 x, uint32 y, uint32 w, uint32 h,
                               uint32 redMask, uint32 greenMask, uint32 blueMask,
                               uint32 redShift, uint32 greenShift, uint32 blueShift);
 static void RasterConvert16to8(uint8 *tof, uint32 line_increment,
-                               uint8 *src, uint32 src_increment,
+                               const uint8 *src, uint32 src_increment,
                                uint32 src_x, uint32 src_y,
                                uint32 x, uint32 y, uint32 w, uint32 h,
                                uint32 redMask, uint32 greenMask, uint32 blueMask,
                                int redShift, int greenShift, int blueShift);
 static void RasterConvertIndexto8(uint8 *tof, uint32 line_increment,
-                                 uint8 *src, uint32 src_increment, uint32 *pixels,
+                                 const uint8 *src, uint32 src_increment,
+                                  const uint32 *pixels,
                                  uint32 src_x, uint32 src_y,
                                  uint32 x, uint32 y, uint32 w, uint32 h,
                                  uint32 redMask, uint32 greenMask, uint32 blueMask,
@@ -263,12 +264,12 @@ Raster_GetBPPDepth(uint32 depth, uint32 bpp)
 
 void
 Raster_ConvertPixels(uint8 *tof, int32 line_increment, int bppdepth,
-                    uint8 *src, int32 src_increment, int src_bppdepth,
-                    Bool pseudoColor, uint32 *pixels,
+                    const uint8 *src, int32 src_increment, int src_bppdepth,
+                    Bool pseudoColor, const uint32 *pixels,
                     uint32 src_x, uint32 src_y,
                     uint32 x, uint32 y, uint32 w, uint32 h)
 {
-   int redShift,greenShift, blueShift;
+   int redShift, greenShift, blueShift;
 
    if (pseudoColor) {
       if (src_bppdepth > 8) {
@@ -539,7 +540,7 @@ Raster_ConvertPixels(uint8 *tof, int32 line_increment, int bppdepth,
 
 uint32
 Raster_ConvertOnePixel(uint32 pix, int src_bppdepth, int bppdepth,
-                      Bool pseudoColor, uint32 *pixels)
+                      Bool pseudoColor, const uint32 *pixels)
 {
    if (pseudoColor) {
       if (src_bppdepth != 8) {
@@ -659,8 +660,10 @@ Raster_ConvertOnePixel(uint32 pix, int src_bppdepth, int bppdepth,
  */
 
 Bool
-Raster_ConversionParameters(int bppdepth, uint32 *redMask,
-                           uint32 *greenMask, uint32 *blueMask)
+Raster_ConversionParameters(int bppdepth,      // IN
+                            uint32 *redMask,   // OUT
+                           uint32 *greenMask, // OUT
+                            uint32 *blueMask)  // OUT
 {
    switch (bppdepth) {
       case 15:
@@ -714,11 +717,12 @@ Raster_ConversionParameters(int bppdepth, uint32 *redMask,
 
 static void
 RasterConvert15to16(uint8 *tof, uint32 line_increment,
-                   uint8 *src, uint32 src_increment,
+                   const uint8 *src, uint32 src_increment,
                    uint32 src_x, uint32 src_y,
                    uint32 x, uint32 y, uint32 w, uint32 h)
 {
-   uint16 *srcptr, *dstptr;
+   const uint16 *srcptr;
+   uint16 *dstptr;
    int i, j;
 
    src_increment >>= 1;
@@ -761,7 +765,7 @@ RasterConvert15to16(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvertShortTo24(uint8 *tof, uint32 line_increment,
-                      uint8 *src, uint32 src_increment,
+                      const uint8 *src, uint32 src_increment,
                       uint32 src_x, uint32 src_y,
                       uint32 x, uint32 y, uint32 w, uint32 h,
                       uint32 redMask, uint32 greenMask, uint32 blueMask,
@@ -769,7 +773,7 @@ RasterConvertShortTo24(uint8 *tof, uint32 line_increment,
                       uint32 greenShift1, uint32 greenShift2,
                       uint32 blueShift1, uint32 blueShift2)
 {
-   uint16 *srcptr;
+   const uint16 *srcptr;
    uint8 *dstptr;
    int i, j, k;
 
@@ -815,7 +819,7 @@ RasterConvertShortTo24(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvertShortTo32(uint8 *tof, uint32 line_increment,
-                      uint8 *src, uint32 src_increment,
+                      const uint8 *src, uint32 src_increment,
                       uint32 src_x, uint32 src_y,
                       uint32 x, uint32 y, uint32 w, uint32 h,
                       uint32 redMask, uint32 greenMask, uint32 blueMask,
@@ -823,7 +827,7 @@ RasterConvertShortTo32(uint8 *tof, uint32 line_increment,
                       uint32 greenShift1, uint32 greenShift2,
                       uint32 blueShift1, uint32 blueShift2)
 {
-   uint16 *srcptr;
+   const uint16 *srcptr;
    uint32 *dstptr;
    int i, j;
 
@@ -873,11 +877,12 @@ RasterConvertShortTo32(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvert16to15(uint8 *tof, uint32 line_increment,
-                   uint8 *src, uint32 src_increment,
+                   const uint8 *src, uint32 src_increment,
                    uint32 src_x, uint32 src_y,
                    uint32 x, uint32 y, uint32 w, uint32 h)
 {
-   uint16 *srcptr, *dstptr;
+   const uint16 *srcptr;
+   uint16 *dstptr;
    int i, j;
 
    src_increment >>= 1;
@@ -919,13 +924,13 @@ RasterConvert16to15(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvert24toShort(uint8 *tof, uint32 line_increment,
-                      uint8 *src, uint32 src_increment,
+                      const uint8 *src, uint32 src_increment,
                       uint32 src_x, uint32 src_y,
                       uint32 x, uint32 y, uint32 w, uint32 h,
                       uint32 redMask, uint32 greenMask, uint32 blueMask,
                       uint32 redShift, uint32 greenShift, uint32 blueShift)
 {
-   uint8 *srcptr;
+   const uint8 *srcptr;
    uint16 *dstptr;
    int i, j, k;
 
@@ -970,11 +975,11 @@ RasterConvert24toShort(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvert24to32(uint8 *tof, uint32 line_increment,
-                   uint8 *src, uint32 src_increment,
+                   const uint8 *src, uint32 src_increment,
                    uint32 src_x, uint32 src_y,
                    uint32 x, uint32 y, uint32 w, uint32 h)
 {
-   uint8 *srcptr;
+   const uint8 *srcptr;
    uint32 *dstptr;
    int i, j, k;
 
@@ -1019,13 +1024,13 @@ RasterConvert24to32(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvert32toShort(uint8 *tof, uint32 line_increment,
-                      uint8 *src, uint32 src_increment,
+                      const uint8 *src, uint32 src_increment,
                       uint32 src_x, uint32 src_y,
                       uint32 x, uint32 y, uint32 w, uint32 h,
                       uint32 redMask, uint32 greenMask, uint32 blueMask,
                       uint32 redShift, uint32 greenShift, uint32 blueShift)
 {
-   uint32 *srcptr;
+   const uint32 *srcptr;
    uint16 *dstptr;
    int i, j;
 
@@ -1069,11 +1074,11 @@ RasterConvert32toShort(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvert32to24(uint8 *tof, uint32 line_increment,
-                   uint8 *src, uint32 src_increment,
+                   const uint8 *src, uint32 src_increment,
                    uint32 src_x, uint32 src_y,
                    uint32 x, uint32 y, uint32 w, uint32 h)
 {
-   uint32 *srcptr;
+   const uint32 *srcptr;
    uint8 *dstptr;
    int i, j, k;
 
@@ -1117,13 +1122,13 @@ RasterConvert32to24(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvertIndexto8(uint8 *tof, uint32 line_increment,
-                         uint8 *src, uint32 src_increment, uint32 *pixels,
+                         const uint8 *src, uint32 src_increment, const uint32 *pixels,
                          uint32 src_x, uint32 src_y,
                          uint32 x, uint32 y, uint32 w, uint32 h,
                          uint32 redMask, uint32 greenMask, uint32 blueMask,
                          uint32 redShift, uint32 greenShift, uint32 blueShift)
 {
-   uint8 *srcptr;
+   const uint8 *srcptr;
    uint8 *dstptr;
    int i, j;
 
@@ -1165,13 +1170,13 @@ RasterConvertIndexto8(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvertIndextoShort(uint8 *tof, uint32 line_increment,
-                         uint8 *src, uint32 src_increment, uint32 *pixels,
+                         const uint8 *src, uint32 src_increment, const uint32 *pixels,
                          uint32 src_x, uint32 src_y,
                          uint32 x, uint32 y, uint32 w, uint32 h,
                          uint32 redMask, uint32 greenMask, uint32 blueMask,
                          uint32 redShift, uint32 greenShift, uint32 blueShift)
 {
-   uint8 *srcptr;
+   const uint8 *srcptr;
    uint16 *dstptr;
    int i, j;
 
@@ -1214,11 +1219,11 @@ RasterConvertIndextoShort(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvertIndexto24(uint8 *tof, uint32 line_increment,
-                      uint8 *src, uint32 src_increment, uint32 *pixels,
+                      const uint8 *src, uint32 src_increment, const uint32 *pixels,
                       uint32 src_x, uint32 src_y,
                       uint32 x, uint32 y, uint32 w, uint32 h)
 {
-   uint8 *srcptr;
+   const uint8 *srcptr;
    uint8 *dstptr;
    int i, j, k;
 
@@ -1260,11 +1265,11 @@ RasterConvertIndexto24(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvertIndexto32(uint8 *tof, uint32 line_increment,
-                      uint8 *src, uint32 src_increment, uint32 *pixels,
+                      const uint8 *src, uint32 src_increment, const uint32 *pixels,
                       uint32 src_x, uint32 src_y,
                       uint32 x, uint32 y, uint32 w, uint32 h)
 {
-   uint8 *srcptr;
+   const uint8 *srcptr;
    uint32 *dstptr;
    int i, j;
 
@@ -1306,13 +1311,13 @@ RasterConvertIndexto32(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvert32to8(uint8 *tof, uint32 line_increment,
-                  uint8 *src, uint32 src_increment,
+                  const uint8 *src, uint32 src_increment,
                   uint32 src_x, uint32 src_y,
                   uint32 x, uint32 y, uint32 w, uint32 h,
                   uint32 redMask, uint32 greenMask, uint32 blueMask,
                   uint32 redShift, uint32 greenShift, uint32 blueShift)
 {
-   uint32 *srcptr;
+   const uint32 *srcptr;
    uint8 *dstptr;
    int i, j;
 
@@ -1356,13 +1361,13 @@ RasterConvert32to8(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvert24to8(uint8 *tof, uint32 line_increment,
-                  uint8 *src, uint32 src_increment,
+                  const uint8 *src, uint32 src_increment,
                   uint32 src_x, uint32 src_y,
                   uint32 x, uint32 y, uint32 w, uint32 h,
                   uint32 redMask, uint32 greenMask, uint32 blueMask,
                   uint32 redShift, uint32 greenShift, uint32 blueShift)
 {
-   uint8 *srcptr;
+   const uint8 *srcptr;
    uint8 *dstptr;
    int i, j, k;
 
@@ -1410,13 +1415,13 @@ RasterConvert24to8(uint8 *tof, uint32 line_increment,
 
 static void
 RasterConvert16to8(uint8 *tof, uint32 line_increment,
-                   uint8 *src, uint32 src_increment,
+                   const uint8 *src, uint32 src_increment,
                    uint32 src_x, uint32 src_y,
                    uint32 x, uint32 y, uint32 w, uint32 h,
                    uint32 redMask, uint32 greenMask, uint32 blueMask,
                    int redShift, int greenShift, int blueShift)
 {
-   uint16 *srcptr;
+   const uint16 *srcptr;
    uint8 *dstptr;
    int i, j;
 
index a146cdcf6484fa8a815c08f0e287b22f83ce94eb..e32db817cccddbbd26c5357d91501a692e5e4b66 100644 (file)
@@ -110,6 +110,7 @@ Equipment Corporation.
 
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #include "region.h"
 
@@ -2569,6 +2570,16 @@ miTranslateRegion(
                   register int x,
                   register int y)
 {
+    /*
+     * This check is here to validate the fix for bug 357509. R_MINSHORT was
+     * defined incorrectly. I changed it to SHRT_MIN, but that introduced the
+     * possibility of a comparison in miTranslateRegionByBoundary underflowing.
+     * miTranslateRegionByBoundary currently uses ints, so it won't underflow
+     * as long as the range of int is larger than the range of short.
+     * This assert checks that that is indeed the case.
+     */
+    ASSERT_ON_COMPILE(INT_MIN < SHRT_MIN);
+
     miTranslateRegionByBoundary(pReg, x, y, R_MINSHORT, R_MAXSHORT);
 }
 
index 0e41037c7774051bf835d72ec22d052d95b79f48..801d1dadd6e63c73a6d36c626ada00d802aa1c8c 100644 (file)
  * str.c --
  *
  *    User level string wrappers
+ *
+ * WARNING:
+ *    Do not call any variadic functions - those that use "..." repeatedly
+ *    with the same va_list or memory corruption and/or crashes will occur.
+ *    The suggested way deal with repeated calls is to use a va_copy:
+ *
+ *    va_list tmpArgs;
+ *
+ *    va_copy(tmpArgs, ap);
+ *    // Call the variadic function
+ *    va_end(tmpArgs);
+ *
  */
 
 #ifdef _WIN32
@@ -119,15 +131,7 @@ Str_Sprintf(char *buf,       // OUT
  *     NB: on overflow the buffer WILL be null terminated at the last
  *     UTF-8 code point boundary within the buffer's bounds.
  *
- * WARNING:
- *      Do not call this function repeatedly with the same va_list
- *      or memory corruption and/or crashes will occur. The suggested
- *      way to deal with this:
- *
- *         va_list tmpArgs;
- *         va_copy(tmpArgs, ap);
- *         // Call this function
- *         va_end(tmpArgs);
+ * WARNING: See warning at the top of this file.
  *
  * Side effects:
  *     None
@@ -516,15 +520,7 @@ Str_SafeAsprintf(size_t *length,       // OUT
  *    ASSERTs or returns NULL on failure, depending on the value of
  *    'assertOnFailure'.
  *
- * WARNING:
- *    Do not call this function repeatedly with the same va_list
- *    or memory corruption and/or crashes will occur. The suggested
- *    way to deal with this:
- *
- *         va_list tmpArgs;
- *         va_copy(tmpArgs, ap);
- *         // Call this function
- *         va_end(tmpArgs);
+ * WARNING: See warning at the top of this file.
  *
  * Side effects:
  *    None
@@ -607,19 +603,10 @@ StrVasprintfInternal(size_t *length,       // OUT:
  * Results:
  *    Returns NULL on failure.
  *
- * WARNING:
- *    Do not call this function repeatedly with the same va_list
- *    or memory corruption and/or crashes will occur. The suggested
- *    way to deal with this:
- *
- *         va_list tmpArgs;
- *         va_copy(tmpArgs, ap);
- *         // Call this function
- *         va_end(tmpArgs);
+ * WARNING: See warning at the top of this file.
  *
  * Side effects:
  *    None
- *
  *-----------------------------------------------------------------------------
  */
 
@@ -642,15 +629,7 @@ Str_Vasprintf(size_t *length,       // OUT
  * Results:
  *    Calls ASSERT_NOT_IMPLEMENTED on failure.
  *
- * WARNING:
- *    Do not call this function repeatedly with the same va_list
- *    or memory corruption and/or crashes will occur. The suggested
- *    way to deal with this:
- *
- *         va_list tmpArgs;
- *         va_copy(tmpArgs, ap);
- *         // Call this function
- *         va_end(tmpArgs);
+ * WARNING: See warning at the top of this file.
  *
  * Side effects:
  *    None
@@ -719,15 +698,7 @@ Str_Swprintf(wchar_t *buf,       // OUT
  *
  *     NB: on overflow the buffer WILL be null terminated
  *
- * WARNING:
- *      Do not call this function repeatedly with the same va_list
- *      or memory corruption and/or crashes will occur. The suggested
- *      way to deal with this:
- *
- *         va_list tmpArgs;
- *         va_copy(tmpArgs, ap);
- *         // Call this function
- *         va_end(tmpArgs);
+ * WARNING: See warning at the top of this file.
  *
  * Side effects:
  *     None
@@ -1026,15 +997,7 @@ Str_Mbscat(char *buf,                // IN-OUT
  *    ASSERTs or returns NULL on failure, depending on the value of
  *    'assertOnFailure'.
  *
- * WARNING:
- *    Do not call this function repeatedly with the same va_list
- *    or memory corruption and/or crashes will occur. The suggested
- *    way to deal with this:
- *
- *         va_list tmpArgs;
- *         va_copy(tmpArgs, ap);
- *         // Call this function
- *         va_end(tmpArgs);
+ * WARNING: See warning at the top of this file.
  *
  * Side effects:
  *    None
@@ -1137,15 +1100,7 @@ Str_Aswprintf(size_t *length,         // OUT
  * Results:
  *    Returns NULL on failure.
  *
- * WARNING:
- *    Do not call this function repeatedly with the same va_list
- *    or memory corruption and/or crashes will occur. The suggested
- *    way to deal with this:
- *
- *         va_list tmpArgs;
- *         va_copy(tmpArgs, ap);
- *         // Call this function
- *         va_end(tmpArgs);
+ * WARNING: See warning at the top of this file.
  *
  * Side effects:
  *    None
@@ -1204,15 +1159,7 @@ Str_SafeAswprintf(size_t *length,         // OUT
  * Results:
  *    Calls ASSERT_NOT_IMPLEMENTED on failure.
  *
- * WARNING:
- *    Do not call this function repeatedly with the same va_list
- *    or memory corruption and/or crashes will occur. The suggested
- *    way to deal with this:
- *
- *         va_list tmpArgs;
- *         va_copy(tmpArgs, ap);
- *         // Call this function
- *         va_end(tmpArgs);
+ * WARNING: See warning at the top of this file.
  *
  * Side effects:
  *    None
index d21c6a1e204365d3602e6a3089e4a1375fdf233c..2a5c6def63fd9ed826216c3338f7cdcb72811437 100644 (file)
@@ -117,7 +117,6 @@ typedef union {
 
 static INLINE Bool SyncWaitQWakeUpNamed(SyncWaitQ *that);
 static INLINE Bool SyncWaitQWakeUpAnon(SyncWaitQ *that);
-static INLINE char *SyncWaitQMakeName(const char *path, uint64 seq);
 
 
 #if __APPLE__
@@ -155,7 +154,7 @@ static Atomic_Int workaround = { WORKAROUND_UNKNOWN, };
  */
 
 static int
-SyncWaitQInit(SyncWaitQ *that) // IN
+SyncWaitQInit(SyncWaitQ *that)  // IN:
 {
    if (UNLIKELY(Atomic_ReadInt(&workaround) == WORKAROUND_UNKNOWN)) {
       struct utsname u;
@@ -165,6 +164,7 @@ SyncWaitQInit(SyncWaitQ *that) // IN
        * We purposedly do not use Hostinfo_OSVersion() to avoid introducing a
        * library dependency just for a workaround.
        */
+
       Atomic_ReadIfEqualWriteInt(&workaround, WORKAROUND_UNKNOWN,
          (   uname(&u) == -1
           || sscanf(u.release, "%u.", &major) != 1
@@ -172,8 +172,9 @@ SyncWaitQInit(SyncWaitQ *that) // IN
    }
 
    ASSERT(Atomic_ReadInt(&workaround) != WORKAROUND_UNKNOWN);
-   return Atomic_ReadInt(&workaround) == WORKAROUND_YES
-             ? pthread_mutex_init(&that->mutex, NULL) : 0;
+
+   return Atomic_ReadInt(&workaround) == WORKAROUND_YES ?
+                                  pthread_mutex_init(&that->mutex, NULL) : 0;
 }
 
 
@@ -223,9 +224,10 @@ SyncWaitQLock(SyncWaitQ *that) // IN
  */
 
 static void
-SyncWaitQUnlock(SyncWaitQ *that) // IN
+SyncWaitQUnlock(SyncWaitQ *that)  // IN:
 {
    ASSERT(Atomic_ReadInt(&workaround) != WORKAROUND_UNKNOWN);
+
    if (Atomic_ReadInt(&workaround) == WORKAROUND_YES) {
       int result;
 
@@ -256,17 +258,17 @@ SyncWaitQUnlock(SyncWaitQ *that) // IN
  */
 
 static void
-SyncWaitQPanicOnFdLimit(int error) // IN
+SyncWaitQPanicOnFdLimit(int error)  // IN:
 {
    switch (error) {
    case EMFILE:
-      Panic("SyncWaitQ: Too many file descriptors are in use by the "
-            "process.\n");
+      Panic("%s: Too many file descriptors are in use by the process.\n",
+            __FUNCTION__);
       break;
 
    case ENFILE:
-      Panic("SyncWaitQ: The system limit on the total number of open files "
-            "has been reached.\n");
+      Panic("%s: The system limit on the total number of open files has "
+            "been reached.\n", __FUNCTION__);
       break;
 
    default:
@@ -303,8 +305,8 @@ SyncWaitQPanicOnFdLimit(int error) // IN
  */
 
 Bool
-SyncWaitQ_Init(SyncWaitQ *that,   // OUT
-              char const *path)  // IN/OPT
+SyncWaitQ_Init(SyncWaitQ *that,   // OUT:
+              char const *path)  // IN/OPT:
 {
    ASSERT(that);
    ASSERT(!path || path[0]);
@@ -349,6 +351,25 @@ SyncWaitQ_Init(SyncWaitQ *that,   // OUT
 }
 
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * SyncWaitQMakeName --
+ *
+ *       Computes the name of the named system object based on the
+ *       path of the wait queue and a sequence number
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+SyncWaitQMakeName(const char *path,  // IN:
+                  uint64 seq)        // IN:
+{
+   return Str_SafeAsprintf(NULL, "%s.%"FMT64"x", path, seq);
+}
+
+
 /*
  *----------------------------------------------------------------------
  *
@@ -365,7 +386,7 @@ SyncWaitQ_Init(SyncWaitQ *that,   // OUT
  */
 
 void
-SyncWaitQ_Destroy(SyncWaitQ *that)
+SyncWaitQ_Destroy(SyncWaitQ *that)  // IN:
 {
    if (!that->initialized) {
       return;
@@ -394,6 +415,7 @@ SyncWaitQ_Destroy(SyncWaitQ *that)
       /*
        * Named
        */
+
       uint64 seq;
       char *name;
 
@@ -417,16 +439,15 @@ SyncWaitQ_Destroy(SyncWaitQ *that)
  *      Add a waiter to the waitqueue.
  *
  * Results:
- *      On success, a pollable handle (fd on Posix and a HANDLE on Win32) that
- *         can be used by the caller to determine when the queue has been woken
- *         up.
- *      On failure, -1.
+ *      On success, a pollable handle (fd on Posix and a HANDLE on Win32)
+ *      that can be used by the caller to determine when the queue has been
+ *      woken up. On failure, -1.
  *
  *-----------------------------------------------------------------------------
  */
 
 PollDevHandle
-SyncWaitQ_Add(SyncWaitQ *that) // IN
+SyncWaitQ_Add(SyncWaitQ *that)  // IN:
 {
    uint64 seq;
    int ret = -1;
@@ -435,17 +456,20 @@ SyncWaitQ_Add(SyncWaitQ *that) // IN
    ASSERT(that);
    ASSERT(that->initialized);
 
-   // Hint that we are about to wait
+   /* Hint that we are about to wait */
    Atomic_Write(&that->waiters, TRUE);
    
-   // The following statement is the demarcation line for Add.  Any
-   // wakeup that happens after this line should wake up this waiter
-   // -- Ticho
+   /*
+    * The following statement is the demarcation line for Add.  Any
+    * wakeup that happens after this line should wake up this waiter
+    * -- Ticho
+    */
+
    seq = Atomic_Read64(&that->seq);
 
    /*
-    * It is OK to fail in the following 2 paths, because if the sequence number
-    * has changed, we manufacture our own fd, so any error is harmless.
+    * It is OK to fail in the following 2 paths, because if the sequence
+    * number has changed, we manufacture our own fd, so any error is harmless.
     */
 
    if (that->pathName == NULL) {
@@ -520,12 +544,18 @@ SyncWaitQ_Add(SyncWaitQ *that) // IN
       }
    }
 
-   // Check to see whether someone didn't wake us up while we were
-   // adding ourselves to the queue
+   /*
+    * Check to see whether someone didn't wake us up while we were
+    * adding ourselves to the queue
+    */
+
    if (seq != Atomic_Read64(&that->seq)) {
-      // Someone woke up the queue while we were adding ourselves to it, so
-      // just pretend that we were woken up too by returning a conjured up,
-      // woken up handle
+      /*
+       * Someone woke up the queue while we were adding ourselves to it, so
+       * just pretend that we were woken up too by returning a conjured up,
+       * woken up handle
+       */
+
       int fd[2];
 
       if (ret >= 0) {
@@ -554,6 +584,7 @@ SyncWaitQ_Add(SyncWaitQ *that) // IN
           * fd[0] now should be in a perpetual woken up state. It will be
           * closed when the client code calls SyncWaitQ_Remove() on it.
           */
+
         ret = fd[0];
       } else {
          close(fd[0]);
@@ -621,7 +652,7 @@ SyncWaitQ_Add(SyncWaitQ *that) // IN
 
 Bool
 SyncWaitQ_Remove(SyncWaitQ *that,       // Unused
-                PollDevHandle handle)  // IN
+                PollDevHandle handle)  // IN:
 {
    ASSERT(that);
    if (!that->initialized) {
@@ -661,7 +692,7 @@ SyncWaitQ_Remove(SyncWaitQ *that,       // Unused
  */
 
 Bool
-SyncWaitQ_WakeUp(SyncWaitQ *that) // IN
+SyncWaitQ_WakeUp(SyncWaitQ *that)  // IN:
 {
    ASSERT(that);
    ASSERT(that->initialized);
@@ -700,7 +731,7 @@ SyncWaitQ_WakeUp(SyncWaitQ *that) // IN
  */
 
 static Bool
-SyncWaitQWakeUpAnon(SyncWaitQ *that)    // IN
+SyncWaitQWakeUpAnon(SyncWaitQ *that)  // IN:
 {
    HandlesAsI64 rwHandles, wakeupHandles;
    int ret;
@@ -720,12 +751,15 @@ SyncWaitQWakeUpAnon(SyncWaitQ *that)    // IN
       return FALSE;
    }
 
-   // The following statement is the demarcation line for wakeup
-   //
-   // There is a possibility for suprious wakeups if the WaitQ_Add
-   // began executing after this line but before the inc of the sequence.
-   //
-   // We assume that spurious wakups are OK.
+   /*
+    * The following statement is the demarcation line for wakeup
+    *
+    * There is a possibility for suprious wakeups if the WaitQ_Add
+    * began executing after this line but before the inc of the sequence.
+    * 
+    * We assume that spurious wakups are OK.
+    */
+
    wakeupHandles.i64 = Atomic_ReadWrite64(&that->rwHandles, rwHandles.i64);
    Atomic_FetchAndInc64(&that->seq);
 
@@ -767,7 +801,7 @@ SyncWaitQWakeUpAnon(SyncWaitQ *that)    // IN
  */
 
 static Bool
-SyncWaitQWakeUpNamed(SyncWaitQ *that)   // IN
+SyncWaitQWakeUpNamed(SyncWaitQ *that)  // IN:
 {
    uint64 seq;
    char *name;
@@ -775,7 +809,7 @@ SyncWaitQWakeUpNamed(SyncWaitQ *that)   // IN
    int ret;
    int error;
 
-   // The following statement is the demarcation line for wakeup
+   /* The following statement is the demarcation line for wakeup */
    seq = Atomic_FetchAndInc64(&that->seq);
    name = SyncWaitQMakeName(that->pathName, seq);
 
@@ -798,11 +832,12 @@ SyncWaitQWakeUpNamed(SyncWaitQ *that)   // IN
        * If error == ENXIO or ENOENT, then there are no waiters, so
        * the wakeup is considered successful.
        */
+
       if (error == ENXIO || error == ENOENT) {
          return TRUE;
       }
 
-      Warning("SyncWaitQWakeUpNamed: open failed, errno = %d\n", error);
+      Warning("%s: open failed, errno = %d\n", __FUNCTION__, error);
       return FALSE;
    }
 
@@ -816,32 +851,15 @@ SyncWaitQWakeUpNamed(SyncWaitQ *that)   // IN
           * just closed the read end of the pipe, we may get an EPIPE
           * error. That's OK, because the waiter was already woken up.
           */
+
          return TRUE;
       }
 
-      Warning("SyncWaitQWakeUpNamed: write failed, ret = %d, errno = %d\n",
+      Warning("%s: write failed, ret = %d, errno = %d\n", __FUNCTION__,
               ret, error);
+
       return FALSE;
    }
 
    return TRUE;
 }
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SyncWaitQMakeName --
- *
- *       Computes the name of the named system object based on the
- *       path of the wait queue and a sequence number
- *
- *----------------------------------------------------------------------
- */
-
-static char *
-SyncWaitQMakeName(const char *path, // IN
-                  uint64 seq)       // IN
-{
-   return Str_SafeAsprintf(NULL, "%s.%"FMT64"x", path, seq);
-}
index cd8d4627385e4855a2d5962fd4bf748926fb8b9a..7bcfa5e883a4819e9d7864236932b1f4f03dcb5b 100644 (file)
@@ -238,7 +238,7 @@ System_GetCurrentTime(int64 *secs,  // OUT
 
 Bool
 System_EnableTimeSlew(int64 delta,            // IN: Time difference in us
-                      uint32 timeSyncPeriod)  // IN: Time interval in 100th of a second
+                      int64 timeSyncPeriod)   // IN: Time interval in us
 {
 #if defined(__FreeBSD__) || defined(sun)
 
@@ -261,10 +261,9 @@ System_EnableTimeSlew(int64 delta,            // IN: Time difference in us
 
    struct timex tx;
    int error;
-   uint64 tick;
-   uint64 timeSyncPeriodUS = timeSyncPeriod * 10000L;
+   int64 tick;
 
-   ASSERT(timeSyncPeriod);
+   ASSERT(timeSyncPeriod > 0);
 
    /*
     * Set the tick so that delta time is corrected in timeSyncPeriod period.
@@ -273,7 +272,8 @@ System_EnableTimeSlew(int64 delta,            // IN: Time difference in us
     * interval.
     */
    tx.modes = ADJ_TICK;
-   tick = (timeSyncPeriodUS + delta) / ((timeSyncPeriod / 100) * USER_HZ);
+   tick = (timeSyncPeriod + delta) /
+          ((timeSyncPeriod / 1000000) * USER_HZ);
    if (tick > TICK_INCR_MAX) {
       tick = TICK_INCR_MAX;
    } else if (tick < TICK_INCR_MIN) {
index 810b59505f4a45104d0f029feb5fb3d2fec22d2b..832c7e4bc8fffdef5b027e33546da60ac507d37f 100644 (file)
@@ -221,7 +221,7 @@ Unity_IsSupported(void)
  *
  * Unity_IsActive --
  *
- *      Determine whether we are in Unity mode at this moment. 
+ *      Determine whether we are in Unity mode at this moment.
  *
  * Results:
  *      TRUE if Unity is active.
@@ -484,13 +484,13 @@ Unity_Exit(void)
    if (unity.isEnabled) {
       /* Hide full-screen detection window for Unity DnD. */
       UnityPlatformUpdateDnDDetWnd(unity.up, FALSE);
-   
+
       /* Kill Unity helper threads. */
       UnityPlatformKillHelperThreads(unity.up);
-   
+
       /* Restore previously saved user settings. */
       UnityPlatformRestoreSystemSettings(unity.up);
-      
+
       unity.isEnabled = FALSE;
    }
 }
@@ -712,7 +712,9 @@ UnityTcloGetWindowPath(char const **result,     // OUT
 
 {
    UnityWindowId window;
-   DynBuf *buf = &gTcloUpdate;
+   DynBuf windowPathUtf8;
+   DynBuf execPathUtf8;
+
    unsigned int index = 0;
    Bool ret = TRUE;
 
@@ -734,20 +736,34 @@ UnityTcloGetWindowPath(char const **result,     // OUT
     * dynbuf passed in does not contain any existing data that needs to be appended to,
     * so this code should continue to accomodate that assumption.
     */
-   DynBuf_SetSize(buf, 0);
-   if (!UnityPlatformGetWindowPath(unity.up, window, buf)) {
+   DynBuf_Destroy(&gTcloUpdate);
+   DynBuf_Init(&gTcloUpdate);
+   DynBuf_Init(&windowPathUtf8);
+   DynBuf_Init(&execPathUtf8);
+   if (!UnityPlatformGetWindowPath(unity.up, window, &windowPathUtf8, &execPathUtf8)) {
       Debug("UnityTcloGetWindowInfo: Could not get window path.\n");
-      return RpcIn_SetRetVals(result, resultLen,
-                              "Could not get window path",
-                              FALSE);
+      ret = RpcIn_SetRetVals(result, resultLen,
+                             "Could not get window path",
+                             FALSE);
+      goto exit;
    }
 
+   /*
+    * Construct the buffer holding the result. Note that we need to use gTcloUpdate
+    * here to avoid leaking during the RPC handler.
+    */
+   DynBuf_Copy(&windowPathUtf8, &gTcloUpdate);
+   DynBuf_Append(&gTcloUpdate, DynBuf_Get(&execPathUtf8), DynBuf_GetSize(&execPathUtf8));
+
    /*
     * Write the final result into the result out parameters and return!
     */
-   *result = (char *)DynBuf_Get(buf);
-   *resultLen = DynBuf_GetSize(buf);
+   *result = (char *)DynBuf_Get(&gTcloUpdate);
+   *resultLen = DynBuf_GetSize(&gTcloUpdate);
 
+exit:
+   DynBuf_Destroy(&windowPathUtf8);
+   DynBuf_Destroy(&execPathUtf8);
    return ret;
 }
 
@@ -1117,11 +1133,23 @@ UnityUpdateCallbackFn(void *param,          // IN: dynbuf
    int i, n, count = 0;
    RegionPtr region;
    char *titleUtf8 = NULL;
+   char *windowPathUtf8 = "";
+   char *execPathUtf8 = "";
 
    switch (update->type) {
 
    case UNITY_UPDATE_ADD_WINDOW:
-      Str_Sprintf(data, sizeof data, "add %u", update->u.addWindow.id);
+      if (DynBuf_GetSize(&update->u.addWindow.windowPathUtf8) > 0) {
+         windowPathUtf8 = DynBuf_Get(&update->u.addWindow.windowPathUtf8);
+      }
+      if (DynBuf_GetSize(&update->u.addWindow.execPathUtf8) > 0) {
+         execPathUtf8 = DynBuf_Get(&update->u.addWindow.execPathUtf8);
+      }
+
+      Str_Sprintf(data, sizeof data, "add %u windowPath=%s execPath=%s",
+                  update->u.addWindow.id,
+                  windowPathUtf8,
+                  execPathUtf8);
       DynBuf_AppendString(buf, data);
       break;
 
@@ -1936,14 +1964,14 @@ error:
  *
  * UnityUpdateState --
  *
- *     Communicate unity state changes to vmx.  
+ *     Communicate unity state changes to vmx.
  *
  * Results:
  *     TRUE if everything is successful.
  *     FALSE otherwise.
  *
  * Side effects:
- *     None. 
+ *     None.
  *
  *----------------------------------------------------------------------------
  */
index a4762036755f104e3e8e87a7441191336f69c849..3647686a5edf5c56c041b9ed45225dcdb974d363 100644 (file)
@@ -67,7 +67,8 @@ void UnityPlatformSaveSystemSettings(UnityPlatform *up);
 void UnityPlatformRestoreSystemSettings(UnityPlatform *up);
 Bool UnityPlatformGetWindowPath(UnityPlatform *up,
                                 UnityWindowId window,
-                                DynBuf *buf);
+                                DynBuf *windowPathUtf8,
+                                DynBuf *execPathUtf8);
 Bool UnityPlatformGetNativeWindowPath(UnityPlatform *up,
                                       UnityWindowId window,
                                       DynBuf *buf);
index e59cdd7115be644ce680a0db769270c4b6567425..f17bdaa6e98e632d6369131b5f293fe1bd316ebe 100644 (file)
@@ -63,15 +63,9 @@ static void USRootWindowsProcessEvent(UnityPlatform *up,
 static int UnityPlatformXErrorHandler(Display *dpy, XErrorEvent *xev);
 static UnitySpecialWindow *UnityPlatformMakeRootWindowsObject(UnityPlatform *up);
 
-#ifdef GTK2
 static gboolean UnityPlatformHandleEventsGlib(GIOChannel *source,
                                               GIOCondition condition,
                                               gpointer data);
-#else
-static void UnityPlatformHandleEventsGdk(gpointer data,
-                                         gint source,
-                                         GdkInputCondition condition);
-#endif
 
 static void UnityPlatformSendClientMessageFull(Display *d,
                                                Window destWindow,
@@ -198,27 +192,6 @@ UnityPlatformInit(UnityWindowTracker *tracker,          // IN
       }
    }
 
-   /*
-    * Set up a callback in the glib main loop to listen for incoming X events on the
-    * unity display connection.
-    */
-#ifdef GTK2
-   {
-      GIOChannel *unityDisplayChannel;
-      unityDisplayChannel = g_io_channel_unix_new(ConnectionNumber(up->display));
-      up->unityDisplayWatchID = g_io_add_watch(unityDisplayChannel,
-                                               G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-                                               UnityPlatformHandleEventsGlib,
-                                               up);
-      g_io_channel_unref(unityDisplayChannel);
-   }
-#else
-   up->unityDisplayWatchID = gdk_input_add(ConnectionNumber(up->display),
-                                           GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
-                                           UnityPlatformHandleEventsGdk,
-                                           up);
-#endif
-
    up->allWindows = HashTable_Alloc(128, HASH_INT_KEY, NULL);
    up->specialWindows = HashTable_Alloc(32, HASH_INT_KEY, NULL);
    up->desktopWindow = NULL;
@@ -327,6 +300,12 @@ UnityPlatformCleanup(UnityPlatform *up) // IN
       return;
    }
 
+   /*
+    * Caller should've called Unity_Exit first.
+    */
+   ASSERT(!up->isRunning);
+   ASSERT(!up->unityDisplayWatchID);
+
    if (up->specialWindows) {
       HashTable_Free(up->specialWindows);
       up->specialWindows = NULL;
@@ -336,15 +315,6 @@ UnityPlatformCleanup(UnityPlatform *up) // IN
       up->allWindows = NULL;
    }
 
-   if (up->unityDisplayWatchID) {
-#ifdef GTK2
-      g_source_remove(up->unityDisplayWatchID);
-#else
-      gdk_input_remove(up->unityDisplayWatchID);
-#endif
-      up->unityDisplayWatchID = 0;
-   }
-
    if (up->display) {
       XCloseDisplay(up->display);
       up->display = NULL;
@@ -795,9 +765,13 @@ UnityPlatformKillHelperThreads(UnityPlatform *up) // IN
    size_t numWindows;
 
    if (!up || !up->isRunning) {
+      ASSERT(!up->unityDisplayWatchID);
       return;
    }
 
+   g_source_remove(up->unityDisplayWatchID);
+   up->unityDisplayWatchID = 0;
+
    up->desktopInfo.numDesktops = 0; // Zero means host has not set virtual desktop config
    UnityX11RestoreSystemSettings(up);
 
@@ -939,6 +913,7 @@ Bool
 UnityPlatformStartHelperThreads(UnityPlatform *up) // IN
 {
    ASSERT(up);
+   ASSERT(!up->unityDisplayWatchID);
 
    XSync(up->display, TRUE);
    up->rootWindows = UnityPlatformMakeRootWindowsObject(up);
@@ -983,6 +958,20 @@ UnityPlatformStartHelperThreads(UnityPlatform *up) // IN
       up->needWorkAreas = NULL;
    }
 
+   /*
+    * Set up a callback in the glib main loop to listen for incoming X events on the
+    * unity display connection.
+    */
+   {
+      GIOChannel *unityDisplayChannel;
+      unityDisplayChannel = g_io_channel_unix_new(ConnectionNumber(up->display));
+      up->unityDisplayWatchID = g_io_add_watch(unityDisplayChannel,
+                                               G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+                                               UnityPlatformHandleEventsGlib,
+                                               up);
+      g_io_channel_unref(unityDisplayChannel);
+   }
+
    return TRUE;
 }
 
@@ -1182,9 +1171,6 @@ UnityPlatformUpdateWindowState(UnityPlatform *up,               // IN
 }
 
 
-#ifdef GTK2
-
-
 /*
  *-----------------------------------------------------------------------------
  *
@@ -1218,49 +1204,6 @@ UnityPlatformHandleEventsGlib(GIOChannel *source,     // IN
 
    return UnityPlatformHandleEvents(errorOccurred, inputAvailable, data);
 }
-#else
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * UnityX11SignalEventsGdk --
- *
- *      Lets the UnityX11 object know that new events are available to process.
- *      This skeleton is used with Gtk+ 1.x.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      Signals the update thread.
- *
- *-----------------------------------------------------------------------------
- */
-
-static void
-UnityPlatformHandleEventsGdk(gpointer data,               // IN
-                             gint source,                 // IN
-                             GdkInputCondition condition) // IN
-{
-   gboolean errorOccurred = FALSE;
-   gboolean inputAvailable = FALSE;
-
-   if (condition & GDK_INPUT_EXCEPTION) {
-      Debug("UnityPlatformHandleEventsGdk - errorOccurred\n");
-      errorOccurred = TRUE;
-   } else if (condition & GDK_INPUT_READ) {
-      inputAvailable = TRUE;
-   }
-
-   if (!UnityPlatformHandleEvents(errorOccurred, inputAvailable, data)) {
-      UnityPlatform *up = (UnityPlatform *) data;
-
-      gdk_input_remove(up->unityDisplayWatchID);
-      up->unityDisplayWatchID = -1;
-   }
-}
-#endif
 
 
 /*
index bc198fd6fa30ce13ac68fb3a9528fa651191e677..0297a5aa6d253bf18b602cf06159c18bc31ba235 100644 (file)
@@ -224,7 +224,7 @@ CompareStackingOrder(UnityPlatform *up,         // IN
    {
       size_t childrenSize = nWindows * sizeof *relevantUChildren;
 
-      if (memcmp(relevantXChildren, relevantUChildren, childrenSize) || 
+      if (memcmp(relevantXChildren, relevantUChildren, childrenSize) ||
           memcmp(relevantXChildren, trackerChildren, childrenSize)) {
          Debug("%s: mismatch!\n", callerName);
          Debug("%s: %8s %10s %10s %10s\n", callerName, "index", "X Server",
@@ -981,8 +981,31 @@ UPWindowSetRelevance(UnityPlatform *up,        // IN
 
    upw->isRelevant = isRelevant;
    if (isRelevant) {
+      DynBuf windowPath;
+      DynBuf execPath;
+      Bool retval;
+
+      DynBuf_Init(&windowPath);
+      DynBuf_Init(&execPath);
+
+      retval = UnityPlatformGetWindowPath(up,
+                                          upw->toplevelWindow,
+                                          &windowPath,
+                                          &execPath);
+
+      if (!retval) {
+         Debug("GetWindowPath didn't know how to identify the window...\n");
+      }
+
       Debug("Adding window %#lx to tracker\n", upw->toplevelWindow);
-      UnityWindowTracker_AddWindowWithData(up->tracker, upw->toplevelWindow, upw);
+      UnityWindowTracker_AddWindowWithData(up->tracker,
+                                           upw->toplevelWindow,
+                                           &windowPath,
+                                           &execPath,
+                                           upw);
+      DynBuf_Destroy(&windowPath);
+      DynBuf_Destroy(&execPath);
+
       UPWindowPushFullUpdate(up, upw);
    } else {
       Debug("Removing window %#lx from tracker\n", upw->toplevelWindow);
@@ -1570,7 +1593,8 @@ UnityPlatformMoveResizeWindow(UnityPlatform *up,         // IN
    } else
 #endif
    {
-      if (up->desktopInfo.currentDesktop == upw->desktopNumber) {
+      if (upw->desktopNumber == up->desktopInfo.currentDesktop ||
+          upw->desktopNumber == -1) {
          UnityRect actualRect;
          Window actualWindow;
 
@@ -1749,7 +1773,6 @@ UnityPlatformArgvToWindowPaths(UnityPlatform *up,        // IN
 
    argv = inArgv;
 
-#ifdef GTK2
    while (argc && AppUtil_AppIsSkippable(argv[0])) {
       argv++;
       argc--;
@@ -1776,7 +1799,6 @@ UnityPlatformArgvToWindowPaths(UnityPlatform *up,        // IN
          return FALSE;
       }
    }
-#endif
 
    /*
     * If the program in question takes any arguments, they will be appended as URI
@@ -2052,8 +2074,8 @@ tryLeader:
  *      Get the information needed to re-launch a window and retrieve further
  *      information on it.
  *
- *      'buf' will hold two URI strings, one which uniquely identifies an X11
- *      window (windowUri) and one which uniquely identifies the window's owning
+ *      windowPathUtf8 uniquely identifies an X11 window (windowUri),
+ *      execPathUtf8 uniquely identifies the window's owning
  *      executable (execUri).
  *
  *      windowUri is handy for getting icons and other data associated with a
@@ -2064,17 +2086,11 @@ tryLeader:
  *      from the same application are really associated with separate
  *      applications.)
  *
- *      I.e., <windowUri><nul><execUri><nul>
- *
- *      This RPC is overloaded with two URIs in order to maintain backwards
- *      compatibility with older VMXs / host UIs expecting to pass the first
- *      (and, to them, only known) URI to GHIGetBinaryInfo.
- *
  * Results:
  *      TRUE if everything went ok, FALSE otherwise.
  *
  * Side effects:
- *      None
+ *      Original buffer contents are overwritten.
  *
  *----------------------------------------------------------------------------
  */
@@ -2082,7 +2098,8 @@ tryLeader:
 Bool
 UnityPlatformGetWindowPath(UnityPlatform *up,        // IN: Platform data
                            UnityWindowId window,     // IN: window handle
-                           DynBuf *buf)              // IN/OUT: full path to the binary
+                           DynBuf *windowPathUtf8,   // IN/OUT: full path to the window
+                           DynBuf *execPathUtf8)     // IN/OUT: full path to the binary
 {
    UnityPlatformWindow *upw;
    Bool retval = FALSE;
@@ -2108,8 +2125,10 @@ UnityPlatformGetWindowPath(UnityPlatform *up,        // IN: Platform data
             "   execUri = %s\n",
             window, windowUri, execUri);
 
-      DynBuf_AppendString(buf, windowUri);
-      DynBuf_AppendString(buf, execUri);
+      DynBuf_SetSize(windowPathUtf8, 0);
+      DynBuf_SetSize(execPathUtf8, 0);
+      DynBuf_AppendString(windowPathUtf8, windowUri);
+      DynBuf_AppendString(execPathUtf8, execUri);
 
       g_free(windowUri);
       g_free(execUri);
index 7b6c49afcba04be2bc98ae321a05a298515a14ac..3ffdfe23af1c5e133c459c08f939e78535a2a670 100644 (file)
 #include <unistd.h>
 #include <stdlib.h>
 
+
+/*
+ * Warn builders up front that GTK 2 is mandatory.
+ */
+#ifndef GTK2
+#   error UnityX11 depends on GTK+ 2.
+#endif
+
+
 /*
  * These defines are listed in the EWMH spec, but not available in any header file that I
  * know of.
@@ -398,11 +407,7 @@ uint32 UnityX11GetCurrentDesktop(UnityPlatform *up);
 void UnityX11SetCurrentDesktop(UnityPlatform *up, uint32 currentDesktop);
 Time UnityPlatformGetServerTime(UnityPlatform *up);
 
-#if GTK_MAJOR_VERSION >= 2
-#   define UnityPlatformProcessMainLoop() g_main_context_iteration(NULL, TRUE)
-#else
-#   define UnityPlatformProcessMainLoop() gtk_main_iteration()
-#endif
+#define UnityPlatformProcessMainLoop() g_main_context_iteration(NULL, TRUE)
 
 int UnityPlatformGetErrorCount(UnityPlatform *up);
 void UnityPlatformResetErrorCount(UnityPlatform *up);
index 232ea7031365029fc31fe9624decb1d54a921659..1a85c35a87c8cb7deeffe163047f293890873e7a 100644 (file)
@@ -71,7 +71,7 @@ UnityWindowTracker_Init(UnityWindowTracker *tracker,     // IN
 {
    memset(tracker, 0, sizeof(UnityWindowTracker));
    tracker->cb = cb;
-   tracker->windows = HashTable_Alloc(128, HASH_INT_KEY, 
+   tracker->windows = HashTable_Alloc(128, HASH_INT_KEY,
                                       (HashTableFreeEntryFn)FreeWindowInfo);
 }
 
@@ -169,17 +169,48 @@ UnityWindowTracker_LookupWindow(UnityWindowTracker *tracker,      // IN
  */
 
 UnityWindowInfo *
-UnityWindowTracker_AddWindow(UnityWindowTracker *tracker,         // IN
-                             UnityWindowId id)                    // IN
+UnityWindowTracker_AddWindow(UnityWindowTracker *tracker,   // IN
+                             UnityWindowId id,              // IN
+                             DynBuf *windowPathUtf8,        // IN
+                             DynBuf *execPathUtf8)          // IN
 {
    UnityWindowInfo *info = UnityWindowTracker_LookupWindow(tracker, id);
    if (!info) {
+      size_t windowPathSize;
+      size_t execPathSize;
+
       info = (UnityWindowInfo *)Util_SafeCalloc(1, sizeof(UnityWindowInfo));
       info->tracker = tracker;
       info->id = id;
       info->type = UNITY_WINDOW_TYPE_NONE;
       info->desktopId = tracker->activeDesktopId;
       DynBuf_Init(&info->titleUtf8);
+      DynBuf_Init(&info->windowPathUtf8);
+      DynBuf_Init(&info->execPathUtf8);
+
+      /*
+       * Ensure that the provided paths only include one NUL terminator
+       * at the end of the buffer, or keep the paths empty otherwise.
+       */
+      windowPathSize = DynBuf_GetSize(windowPathUtf8);
+      if (windowPathSize > 0) {
+         Bool isNullTerminated = Str_Strlen((char *)DynBuf_Get(windowPathUtf8),
+                                            windowPathSize) == windowPathSize - 1;
+         ASSERT(isNullTerminated);
+         if (isNullTerminated) {
+            DynBuf_Copy(windowPathUtf8, &info->windowPathUtf8);
+         }
+      }
+      execPathSize = DynBuf_GetSize(execPathUtf8);
+      if (execPathSize > 0) {
+         Bool isNullTerminated = Str_Strlen((char *)DynBuf_Get(execPathUtf8),
+                                            execPathSize) == execPathSize - 1;
+         ASSERT(isNullTerminated);
+         if (isNullTerminated) {
+            DynBuf_Copy(execPathUtf8, &info->execPathUtf8);
+         }
+      }
+
       LOG(2, ("Unity adding new window (id:%d)\n", id));
       HashTable_Insert(tracker->windows, (const char *)(long)id, info);
       info->changed |= UNITY_CHANGED_ADDED;
@@ -215,11 +246,16 @@ UnityWindowTracker_AddWindow(UnityWindowTracker *tracker,         // IN
  */
 
 UnityWindowInfo *
-UnityWindowTracker_AddWindowWithData(UnityWindowTracker *tracker,         // IN
-                                     UnityWindowId id,                    // IN
-                                     void *data)                          // IN
+UnityWindowTracker_AddWindowWithData(UnityWindowTracker *tracker,    // IN
+                                     UnityWindowId id,               // IN
+                                     DynBuf *windowPathUtf8,         // IN
+                                     DynBuf *execPathUtf8,           // IN
+                                     void *data)                     // IN
 {
-   UnityWindowInfo *info = UnityWindowTracker_AddWindow(tracker, id);
+   UnityWindowInfo *info = UnityWindowTracker_AddWindow(tracker,
+                                                        id,
+                                                        windowPathUtf8,
+                                                        execPathUtf8);
 
    if (info) {
       if (info->data
@@ -816,7 +852,10 @@ UnityWindowTracker_SendUpdate(UnityWindowTracker *tracker,        // IN
 {
    switch (update->type) {
    case UNITY_UPDATE_ADD_WINDOW:
-      UnityWindowTracker_AddWindow(tracker, update->u.addWindow.id);
+      UnityWindowTracker_AddWindow(tracker,
+                                   update->u.addWindow.id,
+                                   &update->u.addWindow.windowPathUtf8,
+                                   &update->u.addWindow.execPathUtf8);
       break;
 
    case UNITY_UPDATE_MOVE_WINDOW:
@@ -1080,6 +1119,8 @@ FreeWindowInfo(UnityWindowInfo *info)              // IN
          miRegionDestroy(info->region);
       }
       DynBuf_Destroy(&info->titleUtf8);
+      DynBuf_Destroy(&info->windowPathUtf8);
+      DynBuf_Destroy(&info->execPathUtf8);
       free(info);
    }
 }
@@ -1234,7 +1275,17 @@ PushUpdates(const char *key,       // IN: window id
       if (!incremental || (info->changed & UNITY_CHANGED_ADDED)) {
          update.type = UNITY_UPDATE_ADD_WINDOW;
          update.u.addWindow.id = id;
+         DynBuf_Init(&update.u.addWindow.windowPathUtf8);
+         DynBuf_Init(&update.u.addWindow.execPathUtf8);
+         if (DynBuf_GetSize(&info->windowPathUtf8)) {
+            DynBuf_Copy(&info->windowPathUtf8, &update.u.addWindow.windowPathUtf8);
+         }
+         if (DynBuf_GetSize(&info->execPathUtf8)) {
+            DynBuf_Copy(&info->execPathUtf8, &update.u.addWindow.execPathUtf8);
+         }
          (*tracker->cb)(tracker->cbparam, &update);
+         DynBuf_Destroy(&update.u.addWindow.windowPathUtf8);
+         DynBuf_Destroy(&update.u.addWindow.execPathUtf8);
       }
       if (!incremental || (info->changed & UNITY_CHANGED_POSITION)) {
          update.type = UNITY_UPDATE_MOVE_WINDOW;
index 09c9af73250c3a6e49d6a7269ee3e7427ac234a6..cde4e7133bfba3a16deb3d80ed04639b7a9a7a6f 100644 (file)
@@ -26,8 +26,8 @@
  *   
  */
 
-#include <stdlib.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <ctype.h>
@@ -81,7 +81,7 @@
 #include <paths.h>
 #endif
 
-#ifndef _PATH_DEVNULL
+#if !defined(_PATH_DEVNULL)
 #define _PATH_DEVNULL "/dev/null"
 #endif
 
 // nothing
 
 
-/*
- * Local functions
- */
-
-#if !defined(__APPLE__) && !defined(__FreeBSD__)
-static char *HostinfoGetCpuInfo(int nCpu, char *name);
-#if !defined(VMX86_SERVER)
-static Bool HostinfoGetMemInfo(char *name, unsigned int *value);
-#endif // ifndef VMX86_SERVER
-#endif // ifndef __APPLE__
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * HostinfoGetLoadAverage --
- *
- *      Returns system average load.
- *
- * Results:
- *      TRUE on success, FALSE otherwise.
- *
- * Side effects:
- *     None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static Bool
-HostinfoGetLoadAverage(float *avg0,  // IN/OUT
-                       float *avg1,  // IN/OUT
-                       float *avg2)  // IN/OUT
-{
-   /* getloadavg(3) was introduced with glibc 2.2 */
-#if defined(GLIBC_VERSION_22) || defined(__APPLE__)
-   double avg[3];
-   int res;
-
-   res = getloadavg(avg, 3);
-   if (res < 3) {
-      NOT_TESTED_ONCE();
-      return FALSE;
-   }
-
-   if (avg0) {
-      *avg0 = (float) avg[0];
-   }
-   if (avg1) {
-      *avg1 = (float) avg[1];
-   }
-   if (avg2) {
-      *avg2 = (float) avg[2];
-   }
-   return TRUE;
-#else
-   /* 
-    * Not implemented. This function is currently only used in the vmx, so
-    * getloadavg is always available to us. If the linux tools ever need this,
-    * we can go back to having a look at the output of /proc/loadavg, but let's
-    * no do that now as long as it's not necessary.
-    */
-   NOT_IMPLEMENTED();
-   return FALSE;
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Hostinfo_GetLoadAverage --
- *
- *      Returns system average load * 100.
- *
- * Results:
- *      TRUE/FALSE
- *
- * Side effects:
- *     None.
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-Hostinfo_GetLoadAverage(uint32 *avg)      // IN/OUT
-{
-   float avg0 = 0;
-
-   if (!HostinfoGetLoadAverage(&avg0, NULL, NULL)) {
-      return FALSE;
-   }
-   *avg = (uint32) 100 * avg0;
-   return TRUE;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Hostinfo_LogLoadAverage --
- *
- *      Logs system average load.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *     None.
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-Hostinfo_LogLoadAverage(void)
-{
-   float avg0 = 0, avg1 = 0, avg2 = 0;
-
-   if (!HostinfoGetLoadAverage(&avg0, &avg1, &avg2)) {
-      return;
-   }
-   Log("LOADAVG: %.2f %.2f %.2f\n", avg0, avg1, avg2);
-}
-
-#if defined(__APPLE__)
-/*
- *-----------------------------------------------------------------------------
- *
- * HostinfoMacAbsTimeNS --
- *
- *      Return the Mac OS absolute time.
- *
- * Results:
- *      The absolute time in nanoseconds is returned. This time is documented
- *      to NEVER go backwards.
- *
- * Side effects:
- *     None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static inline VmTimeType
-HostinfoMacAbsTimeNS(void)
-{
-   VmTimeType raw;
-   mach_timebase_info_data_t *ptr;
-   static Atomic_Ptr atomic; /* Implicitly initialized to NULL. --mbellon */
-
-   /* Insure that the time base values are correct. */
-   ptr = (mach_timebase_info_data_t *) Atomic_ReadPtr(&atomic);
-
-   if (ptr == NULL) {
-      char *p;
-
-      p = Util_SafeMalloc(sizeof(mach_timebase_info_data_t));
-
-      mach_timebase_info((mach_timebase_info_data_t *) p);
-
-      if (Atomic_ReadIfEqualWritePtr(&atomic, NULL, p)) {
-         free(p);
-      }
-
-      ptr = (mach_timebase_info_data_t *) Atomic_ReadPtr(&atomic);
-   }
-
-   raw = mach_absolute_time();
-
-   if ((ptr->numer == 1) && (ptr->denom == 1)) {
-      /* The scaling values are unity, save some time/arithmetic */
-      return raw;
-   } else {
-      /* The scaling values are not unity. Prevent overflow when scaling */
-      return ((double) raw) * (((double) ptr->numer) / ((double) ptr->denom));
-   }
-}
-#endif
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * HostinfoRawSystemTimerUS --
- *
- *      Obtain the raw system timer value.
- *
- * Results:
- *      Relative time in microseconds or zero if a failure.
- *
- * Side effects:
- *     None.
- *
- *-----------------------------------------------------------------------------
- */
-
-VmTimeType
-Hostinfo_RawSystemTimerUS(void)
-{
-#if defined(__APPLE__)
-   return HostinfoMacAbsTimeNS() / 1000ULL;
-#else
-#if defined(VMX86_SERVER)
-   if (HostType_OSIsPureVMK()) {
-      uint64 uptime;
-      VMK_ReturnStatus status;
-
-      status = VMKernel_GetUptimeUS(&uptime);
-      if (status != VMK_OK) {
-         Log("%s: failure!\n", __FUNCTION__);
-         return 0;  // A timer read failure - this is really bad!
-      }
-
-      return uptime;
-   } else {
-#endif /* ifdef VMX86_SERVER */
-      struct timeval tval;
-
-      /* Read the time from the operating system */
-      if (gettimeofday(&tval, NULL) != 0) {
-         Log("%s: failure!\n", __FUNCTION__);
-         return 0;  // A timer read failure - this is really bad!
-      }
-      /* Convert into microseconds */
-      return (((VmTimeType)tval.tv_sec) * 1000000 + tval.tv_usec);
-#if defined(VMX86_SERVER)
-   }
-#endif /* ifdef VMX86_SERVER */
-#endif /* ifdef __APPLE__ */
-}
-
-
 /*
  *-----------------------------------------------------------------------------
  *
@@ -376,6 +146,14 @@ Hostinfo_RawSystemTimerUS(void)
 VmTimeType
 Hostinfo_SystemTimerUS(void)
 {
+#if defined(__APPLE__)
+   /*
+    * On Mac OS a commpage timer is used. Such timers are ensured to never
+    * go backwards so don't use the mutex technique - it's inefficient.
+    */
+
+   return Hostinfo_RawSystemTimerUS();
+#else
    SyncMutex *lck;
    VmTimeType curTime;
    VmTimeType newTime;
@@ -416,6 +194,7 @@ exit:
    SyncMutex_Unlock(lck);
 
    return newTime;
+#endif
 }
 
 /*
@@ -442,7 +221,7 @@ VmTimeType
 Hostinfo_SystemUpTime(void)
 {
 #if defined(__APPLE__)
-   return HostinfoMacAbsTimeNS() / 1000ULL;
+   return Hostinfo_RawSystemTimerUS();
 #elif defined(VMX86_SERVER)
    uint64 uptime;
    VMK_ReturnStatus status;
@@ -522,472 +301,11 @@ Hostinfo_SystemUpTime(void)
    return uptime * 1000 * 1000;
 #else
 NOT_IMPLEMENTED();
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Hostinfo_NameGet --
- *
- *      Return the fully qualified host name of the host.
- *      Thread-safe. --hpreg
- *
- * Results:
- *      The (memorized) name on success
- *      NULL on failure
- *
- * Side effects:
- *      A host name resolution can occur.
- *
- *-----------------------------------------------------------------------------
- */
-
-Unicode
-Hostinfo_NameGet(void)
-{
-   Unicode result;
-
-   static Atomic_Ptr state; /* Implicitly initialized to NULL. --hpreg */
-
-   result = Atomic_ReadPtr(&state);
-
-   if (UNLIKELY(result == NULL)) {
-      Unicode before;
-
-      result = Hostinfo_HostName();
-
-      before = Atomic_ReadIfEqualWritePtr(&state, NULL, result);
-
-      if (before) {
-         Unicode_Free(result);
-
-         result = before;
-      }
-   }
-
-   return result;
-}
-
-
-#ifdef VMX86_SERVER
-/*
- *----------------------------------------------------------------------
- *
- * HostinfoReadProc --
- *
- *      Depending on what string is passed to it, this function parses the
- *      /proc/vmware/sched/ncpus node and returns the requested value.
- *
- * Results:
- *      A postive value on success, -1 (0xFFFFFFFF) on failure.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-
-static INLINE uint32
-HostinfoReadProc(const char *str)
-{
-   /* XXX this should use sysinfo!! (bug 59849)
-    */
-   FILE *f;
-   char *line;
-   uint32 count;
-
-   ASSERT(!strcmp("logical", str) || !strcmp("cores", str) || !strcmp("packages", str)); 
-
-   ASSERT(!HostType_OSIsVMK()); // Don't use /proc/vmware
-
-   f = Posix_Fopen("/proc/vmware/sched/ncpus", "r");
-   if (f != NULL) {
-      while (StdIO_ReadNextLine(f, &line, 0, NULL) == StdIO_Success) {
-         if (strstr(line, str)) {
-            if (sscanf(line, "%d ", &count) == 1) {
-               free(line);
-               break;
-            }
-         }
-         free(line);
-      }
-      fclose(f);
-
-      if (count > 0) {
-         return count;
-      }
-   }
-
-   return -1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Hostinfo_HTDisabled --
- *
- *      Figure out if hyperthreading is enabled
- *
- * Results:
- *      TRUE if hyperthreading is disabled, FALSE otherwise
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-Hostinfo_HTDisabled(void)
-{
-   static uint32 logical = 0, cores = 0;
-
-   if (HostType_OSIsVMK()) {
-      VMK_ReturnStatus status = VMKernel_HTEnabledCPU();
-      if (status != VMK_OK) {
-         return TRUE;
-      } else {
-         return FALSE;
-      }
-   }
-
-   if (logical == 0 && cores == 0) {
-      logical = HostinfoReadProc("logical");
-      cores = HostinfoReadProc("cores");
-      if (logical <= 0 || cores <= 0) {
-         logical = cores = 0;
-      }
-   }
-
-   return logical == cores;
-}
-#endif /*ifdef VMX86_SERVER*/
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Hostinfo_NumCPUs --
- *
- *      Get the number of logical CPUs on the host.  If the CPUs are
- *      hyperthread-capable, this number may be larger than the number of
- *      physical CPUs.  For example, if the host has four hyperthreaded
- *      physical CPUs with 2 logical CPUs apiece, this function returns 8.
- *
- *      This function returns the number of CPUs that the host presents to
- *      applications, which is what we want in the vast majority of cases.  We
- *      would only ever care about the number of physical CPUs for licensing
- *      purposes.
- *
- * Results:
- *      On success, the number of CPUs (> 0) the host tells us we have.
- *      On failure, 0xFFFFFFFF (-1).
- *
- * Side effects:
- *      None
- *
- *-----------------------------------------------------------------------------
- */
-
-uint32
-Hostinfo_NumCPUs(void)
-{
-#if defined(__APPLE__)
-   uint32 out;
-   size_t outSize = sizeof out;
-
-   /*
-    * Quoting sys/sysctl.h:
-    * "
-    * These are the support HW selectors for sysctlbyname.  Parameters that are
-    * byte counts or frequencies are 64 bit numbers. All other parameters are
-    * 32 bit numbers.
-    * ...
-    * hw.activecpu - The number of processors currently available for executing
-    *                threads. Use this number to determine the number threads
-    *                to create in SMP aware applications. This number can
-    *                change when power management modes are changed.
-    * "
-    *
-    * Apparently the only way to retrieve this info is by name, and I have
-    * verified the info changes when you dynamically switch a CPU
-    * offline/online. --hpreg
-    */
-
-   if (sysctlbyname("hw.activecpu", &out, &outSize, NULL, 0) == -1) {
-      return -1;
-   }
-
-   return out;
-#elif defined(__FreeBSD__)
-   uint32 out;
-   size_t outSize = sizeof out;
-
-#if __FreeBSD__version >= 500019
-   if (sysctlbyname("kern.smp.cpus", &out, &outSize, NULL, 0) == -1) {
-      return -1;
-   }
-#else
-   if (sysctlbyname("machdep.smp_cpus", &out, &outSize, NULL, 0) == -1) {
-      if (errno == ENOENT) {
-         out = 1;
-      } else {
-         return -1;
-      }
-   }
-#endif
-
-   return out;
-#else
-   static int count = 0;
-
-   if (count <= 0) {
-#ifdef VMX86_SERVER
-      if (HostType_OSIsVMK()) {
-         VMK_ReturnStatus status = VMKernel_GetNumCPUsUsed(&count);
-         if (status != VMK_OK) {
-            count = 0;
-            return -1;
-         }
-      } else {
-         count = HostinfoReadProc("logical");
-         if (count <= 0) {
-            count = 0;
-            return -1;
-         }
-      }
-#else /* ifdef VMX86_SERVER */
-      FILE *f;
-      char *line;
-
-      f = Posix_Fopen("/proc/cpuinfo", "r");
-      if (f == NULL) { 
-        Msg_Post(MSG_ERROR,
-                 MSGID(hostlinux.opencpuinfo)
-                 "Could not open /proc/cpuinfo.\n");
-        return -1;
-      }
-      
-      while (StdIO_ReadNextLine(f, &line, 0, NULL) == StdIO_Success) {
-        if (strncmp(line, "processor", strlen("processor")) == 0) {
-           count++;
-        }
-        free(line);
-      }
-      
-      fclose(f);
-      
-      if (count == 0) {
-        Msg_Post(MSG_ERROR,
-                 MSGID(hostlinux.readcpuinfo)
-                 "Could not determine the number of processors from "
-                 "/proc/cpuinfo.\n");
-        return -1;
-      }
-#endif /* ifdef VMX86_SERVER */
-   }
-
-   return count;
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Hostinfo_GetRatedCpuMhz --
- *
- *      Get the rated CPU speed of a given processor. 
- *      Return value is in MHz.
- *
- * Results:
- *      TRUE on success, FALSE on failure
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-Hostinfo_GetRatedCpuMhz(int32 cpuNumber, // IN
-                        uint32 *mHz)     // OUT
-{
-#if defined(__APPLE__) || defined(__FreeBSD__)
-
-#  if defined(__APPLE__)
-#     define CPUMHZ_SYSCTL_NAME "hw.cpufrequency_max"
-#  elif __FreeBSD__version >= 50011
-#     define CPUMHZ_SYSCTL_NAME "hw.clockrate"
-#  endif
-
-#  if defined(CPUMHZ_SYSCTL_NAME)
-   uint32 hz;
-   size_t hzSize = sizeof hz;
-
-   // 'cpuNumber' is ignored: Intel Macs are always perfectly symetric.
-
-   if (sysctlbyname(CPUMHZ_SYSCTL_NAME, &hz, &hzSize, NULL, 0) == -1) {
-      return FALSE;
-   }
-
-   *mHz = hz / 1000000;
-   return TRUE;
-#  else
-   return FALSE;
-#  endif
-#else
-   float fMhz = 0;
-   char *readVal = HostinfoGetCpuInfo(cpuNumber, "cpu MHz");
-   
-   if (readVal == NULL) {
-      return FALSE;
-   }
-   
-   if (sscanf(readVal, "%f", &fMhz) == 1) {
-      *mHz = (unsigned int)(fMhz + 0.5);
-   }
-   free(readVal);
-   return TRUE;
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Hostinfo_GetCpuDescription --
- *
- *      Get the descriptive name associated with a given CPU.
- *
- * Results:
- *      On success: Allocated, NUL-terminated string.
- *      On failure: NULL.
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-char *
-Hostinfo_GetCpuDescription(uint32 cpuNumber) // IN
-{
-#if defined(__APPLE__) || defined(__FreeBSD__)
-#  if defined(__APPLE__)
-#     define CPUDESC_SYSCTL_NAME "machdep.cpu.brand_string"
-#  else
-#     define CPUDESC_SYSCTL_NAME "hw.model"
-#  endif
-
-   char *desc;
-   size_t descSize;
-
-   // 'cpuNumber' is ignored: Intel Macs are always perfectly symetric.
-
-   if (sysctlbyname(CPUDESC_SYSCTL_NAME, NULL, &descSize, NULL, 0)
-          == -1) {
-      return NULL;
-   }
-
-   desc = malloc(descSize);
-   if (!desc) {
-      return NULL;
-   }
-
-   if (sysctlbyname(CPUDESC_SYSCTL_NAME, desc, &descSize, NULL, 0)
-          == -1) {
-      free(desc);
-      return NULL;
-   }
-
-   return desc;
-#else
-#ifdef VMX86_SERVER
-   if (HostType_OSIsVMK()) {
-      char mName[48];
-
-      // VMKernel treats mName as an in/out parameter so terminate it.
-      mName[0] = '\0';
-      if (VMKernel_GetCPUModelName(mName, cpuNumber, sizeof(mName)) == VMK_OK) {
-        mName[sizeof(mName) - 1] = '\0';
-         return strdup(mName);
-      }
-      return NULL;
-   }
-#endif
-   return HostinfoGetCpuInfo(cpuNumber, "model name");
-#endif
-}
-
-
-#if !defined(__APPLE__)
-#if !defined(__FreeBSD__)
-/*
- *----------------------------------------------------------------------
- *
- * HostinfoGetCpuInfo --
- *
- *      Get some attribute from /proc/cpuinfo for a given CPU
- *
- * Results:
- *      On success: Allocated, NUL-terminated attribute string.
- *      On failure: NULL.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-
-char *
-HostinfoGetCpuInfo(int nCpu,         // IN 
-                   char *name)       // IN
-{
-   FILE *f;
-   char *line;
-   int cpu = 0;
-   char *value = NULL;
-
-   f = Posix_Fopen("/proc/cpuinfo", "r");
-   if (f == NULL) { 
-      Warning(LGPFX" HostinfoGetCpuInfo: Unable to open /proc/cpuinfo\n");
-      return NULL;
-   }
-      
-   while (cpu <= nCpu && 
-          StdIO_ReadNextLine(f, &line, 0, NULL) == StdIO_Success) {
-      char *s;
-      char *e;
-
-      if ((s = strstr(line, name)) &&
-          (s = strchr(s, ':'))) {
-         s++;
-         e = s + strlen(s);
-
-         /* Skip leading and trailing while spaces */
-         for (; s < e && isspace(*s); s++);
-         for (; s < e && isspace(e[-1]); e--);
-         *e = 0;
-         
-         /* Free previous value */
-         free(value);
-         value = strdup(s);
-         ASSERT_MEM_ALLOC(value);
-         
-         cpu++;
-      }
-      free(line);
-   }     
-
-   fclose(f);
-   return value; 
+#endif
 }
-#endif /* __FreeBSD__ */
 
+
+#if !defined(__APPLE__)
 /*
  *----------------------------------------------------------------------
  *
@@ -1053,9 +371,9 @@ HostinfoFindEntry(char *buffer,         // IN: Buffer
  *----------------------------------------------------------------------
  */
 
-Bool
-HostinfoGetMemInfo(char *name,          //IN
-                   unsigned int *value) //OUT
+static Bool
+HostinfoGetMemInfo(char *name,           // IN:
+                   unsigned int *value)  // OUT:
 {
    size_t len;
    char   buffer[4096];
@@ -1063,7 +381,7 @@ HostinfoGetMemInfo(char *name,          //IN
    int fd = Posix_Open("/proc/meminfo", O_RDONLY);
 
    if (fd == -1) {
-      Warning(LGPFX" HostinfoGetMemInfo: Unable to open /proc/meminfo\n");
+      Warning(LGPFX" %s: Unable to open /proc/meminfo\n", __FUNCTION__);
       return FALSE;
    }
 
@@ -1138,6 +456,7 @@ HostinfoSysinfo(uint64 *totalRam,  // OUT: Total RAM in bytes
        * Kernel versions < 2.3.23. Those kernels used a smaller sysinfo
        * structure, whose last meaningful field is 'procs' --hpreg
        */
+
       si.mem_unit = 1;
    }
 
@@ -1168,8 +487,8 @@ HostinfoSysinfo(uint64 *totalRam,  // OUT: Total RAM in bytes
  *
  * HostinfoGetLinuxMemoryInfoInPages --
  *
- *      Obtain the minimum memory to be maintained, total memory available, and
- *      free memory available on the host (Linux or COS) in pages.
+ *      Obtain the minimum memory to be maintained, total memory available,
+ *      and free memory available on the host (Linux or COS) in pages.
  *
  * Results:
  *      TRUE on success: '*minSize', '*maxSize' and '*currentSize' are set
@@ -1182,9 +501,9 @@ HostinfoSysinfo(uint64 *totalRam,  // OUT: Total RAM in bytes
  */
 
 Bool
-HostinfoGetLinuxMemoryInfoInPages(unsigned int *minSize,     // OUT
-                                  unsigned int *maxSize,     // OUT
-                                  unsigned int *currentSize) // OUT
+HostinfoGetLinuxMemoryInfoInPages(unsigned int *minSize,      // OUT:
+                                  unsigned int *maxSize,      // OUT:
+                                  unsigned int *currentSize)  // OUT:
 {
    uint64 total; 
    uint64 free;
@@ -1215,6 +534,7 @@ HostinfoGetLinuxMemoryInfoInPages(unsigned int *minSize,     // OUT
     * or 32 MB, since the "total" amount of memory reported by Linux is the
     * total physical memory - amount used by the kernel.
     */
+
    if (total < (uint64)128 * 1024 * 1024) {
       total = ROUNDUP(total, (uint64)8 * 1024 * 1024);
    } else {
@@ -1238,7 +558,8 @@ HostinfoGetLinuxMemoryInfoInPages(unsigned int *minSize,     // OUT
  *
  * HostinfoGetSwapInfoInPages --
  *
- *      Obtain the total swap and free swap on the host (Linux or COS) in pages.
+ *      Obtain the total swap and free swap on the host (Linux or COS) in
+ *      pages.
  *
  * Results:
  *      TRUE on success: '*totalSwap' and '*freeSwap' are set if not NULL
@@ -1251,8 +572,8 @@ HostinfoGetLinuxMemoryInfoInPages(unsigned int *minSize,     // OUT
  */
 
 Bool
-Hostinfo_GetSwapInfoInPages(unsigned int *totalSwap,     // OUT
-                            unsigned int *freeSwap)      // OUT
+Hostinfo_GetSwapInfoInPages(unsigned int *totalSwap,  // OUT:
+                            unsigned int *freeSwap)   // OUT:
 {
    uint64 total; 
    uint64 free;
@@ -1279,8 +600,8 @@ Hostinfo_GetSwapInfoInPages(unsigned int *totalSwap,     // OUT
  *
  * Hostinfo_GetMemoryInfoInPages --
  *
- *      Obtain the minimum memory to be maintained, total memory available, and
- *      free memory available on the host in pages.
+ *      Obtain the minimum memory to be maintained, total memory available,
+ *      and free memory available on the host in pages.
  *
  * Results:
  *      TRUE on success: '*minSize', '*maxSize' and '*currentSize' are set
@@ -1293,9 +614,9 @@ Hostinfo_GetSwapInfoInPages(unsigned int *totalSwap,     // OUT
  */
 
 Bool
-Hostinfo_GetMemoryInfoInPages(unsigned int *minSize,     // OUT
-                              unsigned int *maxSize,     // OUT
-                              unsigned int *currentSize) // OUT
+Hostinfo_GetMemoryInfoInPages(unsigned int *minSize,      // OUT:
+                              unsigned int *maxSize,      // OUT:
+                              unsigned int *currentSize)  // OUT:
 {
 #if defined(__APPLE__)
    mach_msg_type_number_t count;
@@ -1310,8 +631,9 @@ Hostinfo_GetMemoryInfoInPages(unsigned int *minSize,     // OUT
     */
 
    count = HOST_VM_INFO_COUNT;
-   error = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&stat,
-                           &count);
+   error = host_statistics(mach_host_self(), HOST_VM_INFO,
+                           (host_info_t) &stat, &count);
+
    if (error != KERN_SUCCESS || count != HOST_VM_INFO_COUNT) {
       Warning("%s: Unable to retrieve host vm stats.\n", __FUNCTION__);
       return FALSE;
@@ -1324,12 +646,14 @@ Hostinfo_GetMemoryInfoInPages(unsigned int *minSize,     // OUT
     * XXX Hopefully this includes cached memory as well. We should check.
     * No. It returns only completely used pages.
     */
+
    *currentSize = stat.free_count;
 
    /*
     * Adding up the stat values does not sum to 100% of physical memory.
     * The correct value is available from sysctl so we do that instead.
     */
+
    if (sysctlbyname("hw.memsize", &memsize, &memsizeSize, NULL, 0) == -1) {
       Warning("%s: Unable to retrieve host vm hw.memsize.\n", __FUNCTION__);
       return FALSE;
@@ -1380,9 +704,9 @@ Hostinfo_GetMemoryInfoInPages(unsigned int *minSize,     // OUT
  */
 
 Bool
-Hostinfo_GetCOSMemoryInfoInPages(unsigned int *minSize,     // OUT
-                                 unsigned int *maxSize,     // OUT
-                                 unsigned int *currentSize) // OUT
+Hostinfo_GetCOSMemoryInfoInPages(unsigned int *minSize,      // OUT:
+                                 unsigned int *maxSize,      // OUT:
+                                 unsigned int *currentSize)  // OUT:
 {
    if (HostType_OSIsPureVMK()) {
       return FALSE;
@@ -1393,551 +717,6 @@ Hostinfo_GetCOSMemoryInfoInPages(unsigned int *minSize,     // OUT
 #endif
 
 
-/*
- *----------------------------------------------------------------------
- *
- * Hostinfo_ResetProcessState --
- *
- *      Clean up signal handlers and file descriptors before an exec().
- *      Fds which need to be kept open can be passed as an array.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-void
-Hostinfo_ResetProcessState(const int *keepFds, // IN:
-                           size_t numKeepFds)  // IN:
-{
-   int s, fd;
-   struct sigaction sa;
-   struct rlimit rlim;
-#ifdef __linux__
-   int err;
-   uid_t euid;
-#endif
-
-   /*
-    * Disable itimers before resetting the signal handlers.
-    * Otherwise, the process may still receive timer signals:
-    * SIGALRM, SIGVTARLM, or SIGPROF.
-    */
-   struct itimerval it;
-   it.it_value.tv_sec = it.it_value.tv_usec = 0;
-   it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
-   setitimer(ITIMER_REAL, &it, NULL);
-   setitimer(ITIMER_VIRTUAL, &it, NULL);
-   setitimer(ITIMER_PROF, &it, NULL);
-
-   for (s = 1; s <= NSIG; s++) {
-      sa.sa_handler = SIG_DFL;
-      sigfillset(&sa.sa_mask);
-      sa.sa_flags = SA_RESTART;
-      sigaction(s, &sa, NULL);
-   }
-   for (fd = (int) sysconf(_SC_OPEN_MAX) - 1; fd > STDERR_FILENO; fd--) {
-      size_t i;
-      for (i = 0; i < numKeepFds; i++) {
-         if (fd == keepFds[i]) {
-            break;
-         }
-      }
-      if (i == numKeepFds) {
-         (void) close(fd);
-      }
-   }
-
-   if (getrlimit(RLIMIT_AS, &rlim) == 0) {
-      rlim.rlim_cur = rlim.rlim_max;
-      setrlimit(RLIMIT_AS, &rlim);
-   }
-
-#ifdef __linux__
-   /*
-    * Drop iopl to its default value.
-    */
-   euid = Id_GetEUid();
-   /* At this point, _unless we are running as root_, we shouldn't have root
-      privileges --hpreg */
-   ASSERT(euid != 0 || getuid() == 0);
-   Id_SetEUid(0);
-   err = iopl(0);
-   Id_SetEUid(euid);
-   ASSERT_NOT_IMPLEMENTED(err == 0);
-#endif
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Hostinfo_Execute --
- *
- *      Start program COMMAND.  If WAIT is TRUE, wait for program
- *     to complete and return exit status.
- *
- * Results:
- *      Exit status of COMMAND.
- *
- * Side effects:
- *      Run a separate program.
- *
- *----------------------------------------------------------------------
- */
-int
-Hostinfo_Execute(const char *command,
-                char * const *args,
-                Bool wait)
-{
-   int pid;
-   int status;
-
-   if (command == NULL) {
-      return 1;
-   }
-
-   pid = fork();
-
-   if (pid == -1) {
-      return -1;
-   }
-
-   if (pid == 0) {
-      Hostinfo_ResetProcessState(NULL, 0);
-      Posix_Execvp(command, args);
-      exit(127);
-   }
-
-   if (wait) {
-      for (;;) {
-        if (waitpid(pid, &status, 0) == -1) {
-           if (errno == ECHILD) {
-              return 0;        // This sucks.  We really don't know.
-           }
-           if (errno != EINTR) {
-              return -1;
-           }
-        } else {
-           return status;
-        }
-      }
-   } else {
-      return 0;
-   }
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Hostinfo_Daemonize --
- *
- *      Cross-platform daemon(3)-like wrapper.
- *
- *      Restarts the current process as a daemon, given the path to the
- *      process (usually from Hostinfo_GetModulePath).  This means:
- *
- *         * You're detached from your parent.  (Your parent doesn't
- *           need to wait for you to exit.)
- *         * Your process no longer has a controlling terminal or
- *           process group.
- *         * Your stdin/stdout/stderr fds are redirected to /dev/null. All
- *           other descriptors, except for the ones that are passed in the
- *           parameter keepFds, are closed.
- *         * Your signal handlers are reset to SIG_DFL in the daemonized
- *           process, and all the signals are unblocked.
- *         * Your main() function is called with the specified NULL-terminated
- *           argument list.
- *
- *      (Don't forget that the first string in args is argv[0] -- the
- *      name of the process).
- *
- *      Unless 'flags' contains HOSTINFO_DAEMONIZE_NOCHDIR, then the
- *      current directory of the daemon process is set to "/".
- *
- *      Unless 'flags' contains HOSTINFO_DAEMONIZE_NOCLOSE, then all stdio
- *      file descriptors of the daemon process are redirected to /dev/null.
- *      This is true even if the stdio descriptors are included in keepFds,
- *      i.e. the list of fds to be kept open.
- *
- *      If 'flags' contains HOSTINFO_DAEMONIZE_EXIT, then upon successful
- *      launch of the daemon, the original process will exit.
- *
- *      If pidPath is non-NULL, then upon success, writes the PID
- *      (as a US-ASCII string followed by a newline) of the daemon
- *      process to that path.
- *
- * Results:
- *      FALSE if the process could not be daemonized.  Err_Errno() contains
- *      the error on failure.
- *      TRUE if 'flags' does not contain HOSTINFO_DAEMONIZE_EXIT and
- *      the process was daemonized.
- *      Otherwise, if the process was daemonized, this function does
- *      not return, and flow continues from your own main() function.
- *
- * Side effects:
- *      The current process is restarted with the given arguments.
- *      The process state is reset (see Hostinfo_ResetProcessState).
- *      A new session is created (so the process has no controlling terminal).
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-Hostinfo_Daemonize(const char *path,             // IN: NUL-terminated UTF-8
-                                                 // path to exec
-                   char * const *args,           // IN: NULL-terminated UTF-8
-                                                 // argv list
-                   HostinfoDaemonizeFlags flags, // IN: flags
-                   const char *pidPath,          // IN/OPT: NUL-terminated
-                                                 // UTF-8 path to write PID
-                   const int *keepFds,           // IN/OPT: array of fds to be
-                                                 // kept open
-                   size_t numKeepFds)            // IN: number of fds in
-                                                 // keepFds
-{
-   /*
-    * We use the double-fork method to make a background process whose
-    * parent is init instead of the original process.
-    *
-    * We do this instead of calling daemon(), because daemon() is
-    * deprecated on Mac OS 10.5 hosts, and calling it causes a compiler
-    * warning.
-    *
-    * We must exec() after forking, because Mac OS library frameworks
-    * depend on internal Mach ports, which are not correctly propagated
-    * across fork calls.  exec'ing reinitializes the frameworks, which
-    * causes them to reopen their Mach ports.
-    */
-   int childPid;
-   int pipeFds[2] = { -1, -1 };
-   uint32 err = EINVAL;
-   char *pathLocalEncoding = NULL;
-   char *pidPathLocalEncoding = NULL;
-   char **argsLocalEncoding = NULL;
-   int *tempFds = NULL;
-   sigset_t sig;
-
-   ASSERT_ON_COMPILE(sizeof (errno) <= sizeof err);
-   ASSERT(args);
-   ASSERT(path);
-   ASSERT(numKeepFds == 0 || keepFds);
-
-   if (pipe(pipeFds) == -1) {
-      err = Err_Errno();
-      Warning("%s: Couldn't create pipe, error %u.\n",
-              __FUNCTION__, err);
-      pipeFds[0] = pipeFds[1] = -1;
-      goto cleanup;
-   }
-
-   numKeepFds++;
-   tempFds = malloc(sizeof tempFds[0] * numKeepFds);
-   if (!tempFds) {
-      err = Err_Errno();
-      Warning("%s: Couldn't allocate memory, error %u.\n",
-              __FUNCTION__, err);
-      goto cleanup;
-   }
-   tempFds[0] = pipeFds[1];
-   if (keepFds) {
-      memcpy(tempFds + 1, keepFds, sizeof tempFds[0] * (numKeepFds - 1));
-   }
-
-   if (fcntl(pipeFds[1], F_SETFD, 1) == -1) {
-      err = Err_Errno();
-      Warning("%s: Couldn't set close-on-exec for fd %d, error %u.\n",
-              __FUNCTION__, pipeFds[1], err);
-      goto cleanup;
-   }
-
-   // Convert the strings from UTF-8 before we fork.
-   pathLocalEncoding = Unicode_GetAllocBytes(path, STRING_ENCODING_DEFAULT);
-   if (!pathLocalEncoding) {
-      Warning("%s: Couldn't convert path [%s] to default encoding.\n",
-              __FUNCTION__, path);
-      goto cleanup;
-   }
-
-   if (pidPath) {
-      pidPathLocalEncoding =
-         Unicode_GetAllocBytes(pidPath, STRING_ENCODING_DEFAULT);
-      if (!pidPathLocalEncoding) {
-         Warning("%s: Couldn't convert path [%s] to default encoding.\n",
-                 __FUNCTION__, pidPath);
-         goto cleanup;
-      }
-   }
-
-   argsLocalEncoding = Unicode_GetAllocList(args, STRING_ENCODING_DEFAULT, -1);
-   if (!argsLocalEncoding) {
-      Warning("%s: Couldn't convert arguments to default encoding.\n",
-              __FUNCTION__);
-      goto cleanup;
-   }
-
-   childPid = fork();
-
-   switch (childPid) {
-   case -1:
-      err = Err_Errno();
-      Warning("%s: Couldn't fork first child, error %u.\n",
-              __FUNCTION__, err);
-      goto cleanup;
-   case 0:
-      // We're the first child.  Continue on.
-      break;
-   default:
-      {
-         // We're the original process.  Check if the first child exited.
-         int status;
-
-         close(pipeFds[1]);
-         waitpid(childPid, &status, 0);
-         if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS) {
-            Warning("%s: Child %d exited with error %d.\n",
-                    __FUNCTION__, childPid, WEXITSTATUS(status));
-            goto cleanup;
-         } else if (WIFSIGNALED(status)) {
-            Warning("%s: Child %d exited with signal %d.\n",
-                    __FUNCTION__, childPid, WTERMSIG(status));
-            goto cleanup;
-         }
-
-         /*
-          * Check if the second child exec'ed successfully.  If it had
-          * an error, it will write a uint32 errno to this pipe before
-          * exiting.  Otherwise, its end of the pipe will be closed on
-          * exec and this call will fail as expected.
-          * The assumption is that we don't get a partial read. In case,
-          * it did happen, we can detect it by the number of bytes read.
-          */
-         while (TRUE) {
-            int res = read(pipeFds[0], &err, sizeof err);
-
-            if (res > 0) {
-               Warning("%s: Child could not exec %s, read %d, error %u.\n",
-                       __FUNCTION__, path, res, err);
-               goto cleanup;
-            } else if (res == -1 && errno == EINTR) {
-               continue;
-            }
-            break;
-         }
-
-         err = 0;
-         goto cleanup;
-      }
-   }
-
-   /*
-    * Close all fds except for the write end of the error pipe (which
-    * we've already set to close on successful exec), and the ones requested by
-    * the caller. Also reset the signal mask to unblock all signals. fork()
-    * clears pending signals.
-    */
-   Hostinfo_ResetProcessState(tempFds, numKeepFds);
-   free(tempFds);
-   tempFds = NULL;
-   sigfillset(&sig);
-   sigprocmask(SIG_UNBLOCK, &sig, NULL);
-
-   if (!(flags & HOSTINFO_DAEMONIZE_NOCLOSE) && setsid() == -1) {
-      Warning("%s: Couldn't create new session, error %d.\n",
-              __FUNCTION__, Err_Errno());
-      _exit(EXIT_FAILURE);
-   }
-
-   switch (fork()) {
-   case -1:
-      {
-         Warning("%s: Couldn't fork second child, error %d.\n",
-                 __FUNCTION__, Err_Errno());
-         _exit(EXIT_FAILURE);
-      }
-   case 0:
-      // We're the second child.  Continue on.
-      break;
-   default:
-      /*
-       * We're the first child.  We don't need to exist any more.
-       *
-       * Exiting here causes the second child to be reparented to the
-       * init process, so the original process doesn't need to wait
-       * for the child we forked off.
-       */
-      _exit(EXIT_SUCCESS);
-   }
-
-   /*
-    * We can't use our i18n wrappers for file manipulation at this
-    * point, since we've forked; internal library mutexes might be
-    * invalid.
-    */
-   if (!(flags & HOSTINFO_DAEMONIZE_NOCHDIR) && chdir("/") == -1) {
-      uint32 err = Err_Errno();
-      Warning("%s: Couldn't chdir to /, error %u.\n",
-              __FUNCTION__, err);
-      // Let the original process know we failed to chdir.
-      if (write(pipeFds[1], &err, sizeof err) == -1) {
-         Warning("Couldn't write to parent pipe: %u, original error: %u.\n",
-                 Err_Errno(), err);
-      }
-      _exit(EXIT_FAILURE);
-   }
-
-   if (!(flags & HOSTINFO_DAEMONIZE_NOCLOSE)) {
-      int fd;
-
-      fd = open(_PATH_DEVNULL, O_RDONLY);
-      if (fd != -1) {
-         dup2(fd, STDIN_FILENO);
-         close(fd);
-      }
-
-      fd = open(_PATH_DEVNULL, O_WRONLY);
-      if (fd != -1) {
-         dup2(fd, STDOUT_FILENO);
-         dup2(fd, STDERR_FILENO);
-         close(fd);
-      }
-   }
-
-   if (pidPath) {
-      int64 pid;
-      char pidString[32];
-      int pidStringLen;
-      int pidPathFd;
-
-      ASSERT_ON_COMPILE(sizeof (pid_t) <= sizeof pid);
-      ASSERT(pidPathLocalEncoding);
-
-      // See above comment about how we can't use our i18n wrappers here.
-      pidPathFd = open(pidPathLocalEncoding, O_WRONLY|O_CREAT|O_TRUNC, 0644);
-
-      if (pidPathFd == -1) {
-         err = Err_Errno();
-         Warning("%s: Couldn't open PID path [%s], error %d.\n",
-                 __FUNCTION__, pidPath, err);
-         if (write(pipeFds[1], &err, sizeof err) == -1) {
-            Warning("Couldn't write to parent pipe: %u, original error: %u.\n",
-                    Err_Errno(), err);
-         }
-         _exit(EXIT_FAILURE);
-      }
-
-      pid = getpid();
-      pidStringLen = Str_Sprintf(pidString, sizeof pidString,
-                                 "%"FMT64"d\n", pid);
-      if (pidStringLen <= 0) {
-         err = EINVAL;
-         if (write(pipeFds[1], &err, sizeof err) == -1) {
-            Warning("Couldn't write to parent pipe: %u, original error: %u.\n",
-                    Err_Errno(), err);
-         }
-         _exit(EXIT_FAILURE);
-      }
-
-      if (write(pidPathFd, pidString, pidStringLen) != pidStringLen) {
-         err = Err_Errno();
-         Warning("%s: Couldn't write PID to path [%s], error %d.\n",
-                 __FUNCTION__, pidPath, err);
-         if (write(pipeFds[1], &err, sizeof err) == -1) {
-            Warning("Couldn't write to parent pipe: %u, original error: %u.\n",
-                    Err_Errno(), err);
-         }
-         _exit(EXIT_FAILURE);
-      }
-
-      close(pidPathFd);
-   }
-
-   if (execv(pathLocalEncoding, argsLocalEncoding) == -1) {
-      err = Err_Errno();
-      Warning("%s: Couldn't exec %s, error %d.\n",
-              __FUNCTION__, path, err);
-      // Let the original process know we failed to exec.
-      if (write(pipeFds[1], &err, sizeof err) == -1) {
-         Warning("Couldn't write to parent pipe: %u, original error: %u.\n",
-                 Err_Errno(), err);
-      }
-      _exit(EXIT_FAILURE);
-   }
-
-   NOT_REACHED();
-
-  cleanup:
-   free(tempFds);
-
-   if (pipeFds[0] != -1) {
-      close(pipeFds[0]);
-   }
-   if (pipeFds[1] != -1) {
-      close(pipeFds[1]);
-   }
-   Util_FreeStringList(argsLocalEncoding, -1);
-   free(pidPathLocalEncoding);
-   free(pathLocalEncoding);
-
-   if (err == 0) {
-      if (flags & HOSTINFO_DAEMONIZE_EXIT) {
-         _exit(EXIT_SUCCESS);
-      }
-   } else {
-      Err_SetErrno(err);
-
-      if (pidPath) {
-         Posix_Unlink(pidPath);
-      }
-   }
-
-   return (err == 0);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Hostinfo_OSIsSMP --
- *
- *      Host OS SMP capability.
- *
- * Results:
- *      TRUE is host OS is SMP capable.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-Hostinfo_OSIsSMP(void)
-{
-   uint32 ncpu;
-
-#if defined(__APPLE__)
-   size_t ncpuSize = sizeof ncpu;
-
-   if (sysctlbyname("hw.ncpu", &ncpu, &ncpuSize, NULL, 0) == -1) {
-      return FALSE;
-   }
-
-#else
-   ncpu = Hostinfo_NumCPUs();
-
-   if (ncpu == 0xFFFFFFFF) {
-      return FALSE;
-   }
-#endif
-
-   return ncpu > 1 ? TRUE : FALSE;
-}
-
 /*
  *-----------------------------------------------------------------------------
  *
@@ -1967,7 +746,7 @@ Hostinfo_OSIsSMP(void)
  */
 
 Unicode
-Hostinfo_GetModulePath(uint32 priv)
+Hostinfo_GetModulePath(uint32 priv)  // IN:
 {
    Unicode path;
 
@@ -2018,152 +797,3 @@ Hostinfo_GetModulePath(uint32 priv)
 
    return path;
 }
-
-
-/*
- *----------------------------------------------------------------------
- *
- *  Hostinfo_TouchBackDoor --
- *
- *      Access the backdoor. This is used to determine if we are 
- *      running in a VM or on a physical host. On a physical host
- *      this should generate a GP which we catch and thereby determine
- *      that we are not in a VM. However some OSes do not handle the
- *      GP correctly and the process continues running returning garbage.
- *      In this case we check the EBX register which should be 
- *      BDOOR_MAGIC if the IN was handled in a VM. Based on this we
- *      return either TRUE or FALSE.
- *
- * Results:
- *      TRUE if we succesfully accessed the backdoor, FALSE or segfault
- *      if not.
- *
- * Side effects:
- *     Exception if not in a VM. 
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-Hostinfo_TouchBackDoor(void)
-{
-   /*
-    * XXX: This can cause Apple's Crash Reporter to erroneously display
-    * a crash, even though the process has caught the SIGILL and handled
-    * it.
-    *
-    * It's also annoying in gdb, so we'll turn it off in devel builds.
-    */
-#if !defined(__APPLE__) && !defined(VMX86_DEVEL)
-   uint32 eax;
-   uint32 ebx;
-   uint32 ecx;
-
-   __asm__ __volatile__(
-#   if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
-      "xchgl %%ebx, %1" "\n\t"
-      "inl %%dx, %%eax" "\n\t"
-      "xchgl %%ebx, %1"
-      : "=a" (eax),
-        "=&rm" (ebx),
-#   else
-      "inl %%dx, %%eax"
-      : "=a" (eax),
-        "=b" (ebx),
-#   endif
-        "=c" (ecx)
-      :        "0" (BDOOR_MAGIC),
-        "1" (~BDOOR_MAGIC),
-        "2" (BDOOR_CMD_GETVERSION),
-        "d" (BDOOR_PORT)
-   );
-   if (ebx == BDOOR_MAGIC) {
-      return TRUE;
-   }
-#endif
-   return FALSE;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Hostinfo_GetUser --
- *
- *      Return current user name, or NULL if can't tell.
- *      XXX Not thread-safe (somebody could do a setenv()). --hpreg
- *
- * Results:
- *      User name.  Must be free()d by caller.
- *
- * Side effects:
- *     No.
- *
- *-----------------------------------------------------------------------------
- */
-
-Unicode
-Hostinfo_GetUser()
-{
-   char buffer[BUFSIZ];
-   struct passwd pw;
-   struct passwd *ppw = &pw;
-   Unicode env = NULL;
-   Unicode name = NULL;
-
-   if ((Posix_Getpwuid_r(getuid(), &pw, buffer, sizeof buffer, &ppw) == 0) &&
-       (ppw != NULL)) {
-      if (ppw->pw_name) {
-         name = Unicode_Duplicate(ppw->pw_name);
-      }
-   }
-
-   if (!name) {
-      env = Posix_Getenv("USER");
-      if (env) {
-         name = Unicode_Duplicate(env);
-      }
-   }
-   return name;
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Hostinfo_LogMemUsage --
- *      Log system memory usage.
- *
- * Results:
- *      System memory usage is logged.
- *
- * Side effects:
- *      No.
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-Hostinfo_LogMemUsage(void)
-{
-   int fd = Posix_Open("/proc/self/statm", O_RDONLY);
-
-   if (fd != -1) {
-      size_t len;
-      char buf[64];
-
-      len = read(fd, buf, sizeof buf);
-      close(fd);
-
-      if (len != -1) {
-         int a[7] = { 0 };
-
-         buf[len < sizeof buf ? len : sizeof buf - 1] = '\0';
-
-         sscanf(buf, "%d %d %d %d %d %d %d",
-                &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]);
-
-         Log("RUSAGE size=%d resident=%d share=%d trs=%d lrs=%d drs=%d dt=%d\n",
-             a[0], a[1], a[2], a[3], a[4], a[5], a[6]);
-      }
-   }
-}
index 657b77d21f5d59ea2d007538af0f1e333fb66ed6..42d9d9753cc346e2e1e9b5011c6cdeb522bca5bd 100644 (file)
@@ -99,11 +99,14 @@ static int UtilTokenHasGroup(HANDLE token, SID *group);
 #ifdef UTIL_BACKTRACE_USE_UNWIND
 #include <unwind.h>
 
+#define MAX_SKIPPED_FRAMES 10
+
 struct UtilBacktraceFromPointerData {
    uintptr_t        basePtr;
    Util_OutputFunc  outFunc;
    void            *outFuncData;
    unsigned int     frameNr;
+   unsigned int     skippedFrames;
 };
 
 struct UtilBacktraceToBufferData {
@@ -373,6 +376,7 @@ UtilBacktraceFromPointerCallback(struct _Unwind_Context *ctx, // IN: Unwind cont
    /*
     * Stack grows down.  So if we are below basePtr, do nothing...
     */
+
    if (cfa >= data->basePtr && data->frameNr < 500) {
 #ifndef VM_X86_64
 #   error You should not build this on 32bit - there is no eh_frame there.
@@ -389,6 +393,14 @@ UtilBacktraceFromPointerCallback(struct _Unwind_Context *ctx, // IN: Unwind cont
                     _Unwind_GetGR(ctx, 14), _Unwind_GetGR(ctx, 15));
       data->frameNr++;
       return _URC_NO_REASON;
+   } else if (data->skippedFrames < MAX_SKIPPED_FRAMES && !data->frameNr) {
+      /*
+       * Skip over the frames before the specified starting point of the
+       * backtrace.
+       */
+
+      data->skippedFrames++;
+      return _URC_NO_REASON;
    }
    return _URC_END_OF_STACK;
 }
@@ -422,6 +434,7 @@ UtilSymbolBacktraceFromPointerCallback(struct _Unwind_Context *ctx, // IN: Unwin
    /*
     * Stack grows down.  So if we are below basePtr, do nothing...
     */
+
    if (cfa >= data->basePtr && data->frameNr < 500) {
 #ifndef VM_X86_64
 #   error You should not build this on 32bit - there is no eh_frame there.
@@ -450,6 +463,14 @@ UtilSymbolBacktraceFromPointerCallback(struct _Unwind_Context *ctx, // IN: Unwin
       }
       data->frameNr++;
       return _URC_NO_REASON;
+   } else if (data->skippedFrames < MAX_SKIPPED_FRAMES && !data->frameNr) {
+      /*
+       * Skip over the frames before the specified starting point of the
+       * backtrace.
+       */
+
+      data->skippedFrames++;
+      return _URC_NO_REASON;
    }
    return _URC_END_OF_STACK;
 }
@@ -511,6 +532,7 @@ Util_BacktraceFromPointerWithFunc(uintptr_t *basePtr,
    data.outFunc = outFunc;
    data.outFuncData = outFuncData;
    data.frameNr = 0;
+   data.skippedFrames = 0;
    _Unwind_Backtrace(UtilBacktraceFromPointerCallback, &data);
 
 #if !defined(_WIN32) && !defined(N_PLAT_NLM) && !defined(VMX86_TOOLS)
@@ -523,6 +545,7 @@ Util_BacktraceFromPointerWithFunc(uintptr_t *basePtr,
    data.outFunc = outFunc;
    data.outFuncData = outFuncData;
    data.frameNr = 0;
+   data.skippedFrames = 0;
    _Unwind_Backtrace(UtilSymbolBacktraceFromPointerCallback, &data);
 #endif
 
index 8a968f4ed0778004505136bb8cd39bf5847c0746..828fc7012b690c6f16eb29e9a05b534a12404c94 100644 (file)
@@ -34,6 +34,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <dirent.h>
+#include <ctype.h>
 
 #if !__FreeBSD__ && !sun
 #   include <pwd.h>
 #include "unicodeOperations.h"
 #include "err.h"
 #include "posix.h"
+#include "vmstdio.h"
+
+#define LOGLEVEL_MODULE util
+#include "loglevel_user.h"
+#define LGPFX "UtilPosix:"
 
 
 /* For Util_GetProcessName() */
 #   endif
 #endif
 
+#if defined(VMX86_STATS) && defined(__linux__) && !defined(VMX86_SERVER)
+#define SYS_CSTATE_DIR  "/sys/devices/system/cpu"
+#define PROC_CSTATE_DIR "/proc/acpi/processor"
+#define MAX_C_STATES    8
+#define FREQ_ACPI       3.579545
+#endif
 
 
 #if !__FreeBSD__ && !sun
@@ -667,7 +679,8 @@ Util_GetProcessName(pid_t pid,         // IN : process id
 
    fd = Posix_Open(fileName, O_RDONLY);
    if (fd < 0) {
-      Log("Util_GetProcessName: Error: cannot open %s\n", fileName);
+      Log("%s: Error: cannot open %s\n", __FUNCTION__, fileName);
+
       return FALSE;
    }
 
@@ -677,8 +690,9 @@ Util_GetProcessName(pid_t pid,         // IN : process id
 #else
    if (nread < 0) {
 #endif
-      Log("Util_GetProcessName: Error: could not read %s\n", fileName);
+      Log("%s: Error: could not read %s\n", __FUNCTION__, fileName);
       close(fd);
+
       return FALSE;
    }
 
@@ -694,7 +708,8 @@ Util_GetProcessName(pid_t pid,         // IN : process id
     * contains a format modifier to ensure psinfo is not overrun.
     */
    if (sscanf(buf, PRE PSINFOFMT POST, psinfo) != 1) {
-      Log("Util_GetProcessName: Error, could not parse contents of %s\n", fileName);
+      Log("%s: Error, could not parse contents of %s\n", __FUNCTION__,
+          fileName);
       return FALSE;
    }
 
@@ -705,8 +720,9 @@ Util_GetProcessName(pid_t pid,         // IN : process id
 
    psnameLen = strlen(psname);
    if (psnameLen + 1 > bufOutSize) {
-      Log("Util_GetProcessName: Error, process name (%"FMTSZ"u bytes) is larger "
-          "than output buffer\n", psnameLen);
+      Log("%s: Error, process name (%"FMTSZ"u bytes) is larger "
+          "than output buffer\n", __FUNCTION__, psnameLen);
+
       return FALSE;
    }
 
@@ -714,3 +730,390 @@ Util_GetProcessName(pid_t pid,         // IN : process id
    return TRUE;
 }
 #endif
+
+#if defined(VMX86_STATS)
+#if defined(__linux__) && !defined(VMX86_SERVER)
+/*
+ *----------------------------------------------------------------------------
+ *
+ * UtilAllocCStArrays --
+ *
+ *      (Re-)Allocate data arrays for UtilReadSysCStRes and UtilReadProcCStRes.
+ *
+ * Results:
+ *      TRUE if successful.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static Bool
+UtilAllocCStArrays(uint32 ncpus,        // IN
+                   uint32 nstates,      // IN
+                   uint64 **transitns,  // OUT
+                   uint64 **residency,  // OUT
+                   uint64 **transTime,  // OUT
+                   uint64 **residTime)  // OUT
+{
+   free(*transitns);
+   free(*residency);
+   free(*transTime);
+   free(*residTime);
+
+   *transitns = calloc(nstates * ncpus, sizeof **transitns);
+   *residency = calloc(nstates * ncpus, sizeof **residency);
+   *transTime = calloc(ncpus, sizeof **transTime);
+   *residTime = calloc(ncpus, sizeof **residTime);
+
+   if (!*transitns || !*residency || !*transTime || !*residTime) {
+      free(*transitns);
+      free(*residency);
+      free(*transTime);
+      free(*residTime);
+      Warning("%s: Cannot allocate memory for C-state queries\n", __FUNCTION__);
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * UtilReadSysCStRes --
+ * UtilReadProcCStRes --
+ *
+ *      Read the C-state residency statistics under /sys and /proc
+ *      respectively. UtilReadSysCStRes should take precedence over
+ *      UtilReadProcCStRes as /proc/acpi is getting replaced by sysfs
+ *      in newer kernels. See Util_QueryCStResidency for description of
+ *      parameters.
+ *
+ * Results:
+ *      TRUE if successful.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static Bool
+UtilReadSysCStRes(DIR *dir,                     // IN
+                  uint32 *numCpus,              // IN/OUT
+                  uint32 *numCStates,           // IN/OUT
+                  uint64 **transitns,           // OUT
+                  uint64 **residency,           // OUT
+                  uint64 **transTime,           // OUT
+                  uint64 **residTime)           // OUT
+{
+   struct dirent *cpuEntry;
+   DIR *cpuDir;
+   struct dirent *cstateEntry;
+   char pathname[PATH_MAX + 1];
+   uint32 cpu = 0;
+   uint32 cl = 0;
+
+   /* Determine the number of cpus and c-states. */
+   while ((cpuEntry = readdir(dir))) {
+      if (Str_Strncasecmp(cpuEntry->d_name, "cpu", 3) == 0 &&
+          isdigit(cpuEntry->d_name[3])) {
+         cpu++;
+         if (cl != 0) {         /* already found the number of c states */
+            continue;
+         }
+         if (Str_Snprintf(pathname, sizeof pathname,
+                          SYS_CSTATE_DIR"/%s/cpuidle", cpuEntry->d_name) <= 0) {
+            LOG(0, ("%s: Str_Snprintf failed\n", __FUNCTION__));
+            return FALSE;
+         }
+         cpuDir = Posix_OpenDir(pathname);
+         if (cpuDir != NULL) {
+            uint32 cnum;
+
+            while ((cstateEntry = readdir(cpuDir))) {
+               if (Str_Strncasecmp(cstateEntry->d_name, "state", 5) == 0 &&
+                   sscanf(cstateEntry->d_name + 5, "%u", &cnum) == 1 &&
+                   cnum > cl) {
+                  cl = cnum;    /* state0 will be ignored */
+               }
+            }
+            closedir(cpuDir);
+         }
+      }
+   }
+   if (cpu == 0 || cl == 0) {
+      return FALSE;
+   }
+
+   if (*numCpus != cpu || *numCStates != cl) {
+      if (!UtilAllocCStArrays(cpu, cl, transitns, residency, transTime,
+                              residTime)) {
+         return FALSE;
+      }
+      *numCpus = cpu;
+      *numCStates = cl;
+   }
+
+   rewinddir(dir);
+   cpu = 0;
+   while ((cpuEntry = readdir(dir))) {
+      int pathlen;
+      VmTimeType timeUS;
+
+      if (Str_Strncasecmp(cpuEntry->d_name, "cpu", 3) != 0 ||
+          !isdigit(cpuEntry->d_name[3])) {
+         continue;
+      }
+      pathlen = Str_Snprintf(pathname, sizeof pathname,
+                             SYS_CSTATE_DIR"/%s/cpuidle", cpuEntry->d_name);
+      if (pathlen <= 0) {
+         LOG(0, ("%s: Str_Snprintf for '%s/cpuidle' failed\n", __FUNCTION__,
+                 cpuEntry->d_name));
+         return FALSE;
+      }
+      cpuDir = Posix_OpenDir(pathname);
+      if (cpuDir == NULL) {
+         LOG(0, ("%s: Failed to open directory %s\n", __FUNCTION__, pathname));
+         continue;
+      }
+
+      /*
+       * Under the "cpuidle" directory, there is one "stateX" directory for
+       * each C-state.  We ignore "state0", i.e. C0, which is the running state.
+       * Under each "stateX" directory, there is a "usage" file which contains
+       * the number of entries into that state, and a "time" file which
+       * contains the total residency in that state.
+       */
+
+      while ((cstateEntry = readdir(cpuDir))) {
+         FILE *statsFile;
+         int result;
+         uint32 index;
+
+         if (Str_Strncasecmp(cstateEntry->d_name, "state", 5) != 0) {
+            continue;
+         }
+         if (sscanf(cstateEntry->d_name + 5, "%u", &cl) != 1 || cl == 0) {
+            continue;
+         }
+         cl--;          /* ignoring state0 -- cl == 0 -> state1 */
+         index = *numCStates * cpu + cl;
+
+         if (Str_Snprintf(pathname + pathlen, sizeof pathname - pathlen,
+                          "/%s/usage", cstateEntry->d_name) <= 0) {
+            LOG(0, ("%s: Str_Snprintf for 'usage' failed\n", __FUNCTION__));
+            closedir(cpuDir);
+            return FALSE;
+         }
+         statsFile = Posix_Fopen(pathname, "r");
+         if (statsFile == NULL) {
+            continue;
+         }
+         result = fscanf(statsFile, "%"FMT64"u", &(*transitns)[index]);
+         fclose(statsFile);
+         if (result <= 0) {
+            continue;
+         }
+
+         if (Str_Snprintf(pathname + pathlen, sizeof pathname - pathlen,
+                          "/%s/time", cstateEntry->d_name) <= 0) {
+            LOG(0, ("%s: Str_Snprintf for 'time' failed\n", __FUNCTION__));
+            closedir(cpuDir);
+            return FALSE;
+         }
+         statsFile = Posix_Fopen(pathname, "r");
+         if (statsFile == NULL) {
+            continue;
+         }
+         result = fscanf(statsFile, "%"FMT64"u", &(*residency)[index]);
+         fclose(statsFile);
+         if (result <= 0) {
+            continue;
+         }
+      }
+      closedir(cpuDir);
+
+      timeUS = Hostinfo_SystemTimerUS();
+      if (timeUS <= 0) {
+         LOG(0, ("%s: Hostinfo_SystemTimerUS() failed\n", __FUNCTION__));
+         return FALSE;
+      }
+      (*transTime)[cpu] = timeUS;
+      (*residTime)[cpu] = timeUS;
+      cpu++;
+   }
+
+   return cpu > 0;
+}
+
+
+static Bool
+UtilReadProcCStRes(DIR *dir,                    // IN
+                   uint32 *numCpus,             // IN/OUT
+                   uint32 *numCStates,          // IN/OUT
+                   uint64 **transitns,          // OUT
+                   uint64 **residency,          // OUT
+                   uint64 **transTime,          // OUT
+                   uint64 **residTime)          // OUT
+{
+   struct dirent *cpuEntry;
+   uint32 cpu = 0;
+
+   /* Determine the number of cpus. */
+   while ((cpuEntry = readdir(dir))) {
+      if (cpuEntry->d_name[0] != '.') {
+         cpu++;
+      }
+   }
+   if (cpu == 0) {
+      return FALSE;
+   }
+
+   if (*numCpus != cpu) {
+      /*
+       * We do not know the number of C-states supported until we read the
+       * file, so we allocate for MAX_C_STATES and determine *numCStates later.
+       */
+
+      if (!UtilAllocCStArrays(cpu, MAX_C_STATES, transitns, residency,
+                              transTime, residTime)) {
+         return FALSE;
+      }
+      *numCpus = cpu;
+      *numCStates = 0;
+   }
+
+   rewinddir(dir);
+   cpu = 0;
+   while ((cpuEntry = readdir(dir))) {
+      char pathname[PATH_MAX + 1];
+      char *line;
+      size_t lineSize;
+      FILE *powerFile;
+      uint32 cl;
+      VmTimeType timeUS;
+
+      if (cpuEntry->d_name[0] == '.') {
+         continue;
+      }
+      if (Str_Snprintf(pathname, sizeof pathname, PROC_CSTATE_DIR"/%s/power",
+                       cpuEntry->d_name) <= 0) {
+         LOG(0, ("%s: Str_Snprintf for '%s/power' failed\n", __FUNCTION__,
+                 cpuEntry->d_name));
+         return FALSE;
+      }
+      powerFile = Posix_Fopen(pathname, "r");
+      if (powerFile == NULL) {
+         continue;
+      }
+
+      cl = 0;
+      while (StdIO_ReadNextLine(powerFile, &line, 0, &lineSize)
+             == StdIO_Success) {
+         char *ptr;
+         uint32 index = *numCStates * cpu + cl;
+
+         if ((ptr = Str_Strnstr(line, "usage[", lineSize))) {
+            sscanf(ptr + 6, "%"FMT64"u]", &(*transitns)[index]);
+            if ((ptr = Str_Strnstr(line, "duration[", lineSize))) {
+               sscanf(ptr + 9, "%"FMT64"u]", &(*residency)[index]);
+               cl++;
+            }
+         }
+         free(line);
+      }
+      fclose(powerFile);
+
+      timeUS = Hostinfo_SystemTimerUS();
+      if (timeUS <= 0) {
+         LOG(0, ("%s: Hostinfo_SystemTimerUS() failed\n", __FUNCTION__));
+         return FALSE;
+      }
+      (*transTime)[cpu] = timeUS;
+      (*residTime)[cpu] = (uint64)((double)timeUS * FREQ_ACPI);
+      if (*numCStates == 0) {
+         *numCStates = cl;
+      }
+      cpu++;
+   }
+   return cpu > 0 && *numCStates > 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * Util_QueryCStResidency --
+ *
+ *      Query CPU's C-state residency statistics exposed by the host OS.
+ *      On Linux, this is done via either the sysfs or /proc/acpi interface.
+ *
+ *      The parameters transitns, residency, transTime and residTime are
+ *      pointers to uint64 arrays, whose dimensions are specified by
+ *      *numCpus and/or *numCStates:
+ *      transitns -- number of trasitions into each c-state for each CPU
+ *      residency -- time in each c-state for each CPU (in some opaque unit)
+ *      transTime -- timestamp (microseconds) for transitns data, per CPU
+ *      residTime -- timestamp for residency data, per CPU (in same unit as
+ *                   residency)
+ *
+ *      If the dimensions specified are too small, the arrays are freed
+ *      and new memory allocated.
+ *
+ * Results:
+ *      TRUE if successful.
+ *
+ * Side Effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+Util_QueryCStResidency(uint32 *numCpus,         // IN/OUT
+                       uint32 *numCStates,      // IN/OUT
+                       uint64 **transitns,      // OUT
+                       uint64 **residency,      // OUT
+                       uint64 **transTime,      // OUT
+                       uint64 **residTime)      // OUT
+{
+   DIR *dir;
+   Bool ret = FALSE;
+
+   dir = Posix_OpenDir(SYS_CSTATE_DIR);
+   if (dir) {
+      ret = UtilReadSysCStRes(dir, numCpus, numCStates, transitns, residency,
+                              transTime, residTime);
+      closedir(dir);
+   }
+
+   if (!ret) {
+      dir = Posix_OpenDir(PROC_CSTATE_DIR);
+      if (dir) {
+         ret = UtilReadProcCStRes(dir, numCpus, numCStates, transitns,
+                                  residency, transTime, residTime);
+         closedir(dir);
+      }
+   }
+
+   return ret;
+}
+
+#else   // #if defined(__linux__) && !defined(VMX86_SERVER)
+
+Bool
+Util_QueryCStResidency(uint32 *numCpus,         // IN/OUT
+                       uint32 *numCStates,      // IN/OUT
+                       uint64 **transitns,      // OUT
+                       uint64 **residency,      // OUT
+                       uint64 **transTime,      // OUT
+                       uint64 **residTime)      // OUT
+{
+   return FALSE;
+}
+#endif
+#endif  // #if defined(VMX86_STATS)
index 16a54b862194013c6b8a2d49359b5bc62e0b9046..3c3cfcedd6db2bdb90ebc16528713c2ad381b5c3 100644 (file)
@@ -3248,9 +3248,26 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
    Bool impersonatingVMWareUser = FALSE;
    void *userToken = NULL;
    char *destPtr;
-#ifdef linux
    char *endDestPtr;
+#if defined(_WIN32) || defined(linux)
    VixCommandListFileSystemsRequest *lfReq = (VixCommandListFileSystemsRequest *) requestMsg;
+   const char *listFileSystemsFormatString = "<filesystem>"
+                                             "<name>%s</name>"
+                                             "<size>%"FMT64"u</size>"
+                                             "<freeSpace>%"FMT64"u</freeSpace>"
+                                             "<type>%s</type>"
+                                             "</filesystem>";
+#endif
+#if defined(_WIN32)
+   Unicode *driveList = NULL;
+   int numDrives = -1;
+   uint64 freeBytesToUser = 0;
+   uint64 totalBytesToUser = 0;
+   uint64 freeBytes = 0;
+   Unicode fileSystemType;
+   int i;
+#endif
+#ifdef linux
    MNTHANDLE fp;
    DECLARE_MNTINFO(mnt);
    const char *mountfile = NULL;
@@ -3260,6 +3277,7 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
 
    destPtr = resultBuffer;
    *destPtr = 0;
+   endDestPtr = resultBuffer + sizeof(resultBuffer);
 
    err = VixToolsImpersonateUser(requestMsg, &userToken);
    if (VIX_OK != err) {
@@ -3268,11 +3286,57 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
    impersonatingVMWareUser = TRUE;
 
 #if defined(_WIN32)
-   // XXX TBD
-   err = VIX_E_NOT_SUPPORTED;
-#elif defined(linux)
+   numDrives = Win32U_GetLogicalDriveStrings(&driveList);
+   if (-1 == numDrives) {
+      Warning("unable to get drive listing: windows error code %d\n",
+              GetLastError());
+      err = FoundryToolsDaemon_TranslateSystemErr();
+      goto abort;
+   }
 
-   endDestPtr = resultBuffer + sizeof(resultBuffer);
+   for (i = 0; i < numDrives; i++) {
+      /*
+       * Only add to the list if it is a local drive or
+       * VIX_FILESYSTEMS_HIDE_NETWORK is not set
+       */
+      if ((DRIVE_REMOTE != Win32U_GetDriveType(driveList[i])) ||
+          !(lfReq->options & VIX_FILESYSTEMS_HIDE_NETWORK)) {
+
+         if (!Win32U_GetDiskFreeSpaceEx(driveList[i],
+                                        (PULARGE_INTEGER) &freeBytesToUser,
+                                        (PULARGE_INTEGER) &totalBytesToUser,
+                                        (PULARGE_INTEGER) &freeBytes)) {
+            /*
+             * If we encounter an error, just return 0 values for the space info
+             */
+            freeBytesToUser = 0;
+            totalBytesToUser = 0;
+            freeBytes = 0;
+
+            Warning("unable to get drive size info: windows error code %d\n",
+                    GetLastError());
+         }
+
+         // If it fails, fileSystemType will be NULL
+         Win32U_GetVolumeInformation(driveList[i],
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     &fileSystemType);
+
+         destPtr += Str_Sprintf(destPtr, endDestPtr - destPtr,
+                                listFileSystemsFormatString,
+                                driveList[i],
+                                totalBytesToUser,
+                                freeBytesToUser,
+                                fileSystemType);
+
+         Unicode_Free(fileSystemType);
+      }
+   }
+
+#elif defined(linux)
 
    if (lfReq->options & VIX_FILESYSTEMS_HIDE_NETWORK) {
       mountfile = "/etc/fstab";
@@ -3299,12 +3363,7 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
       size = (uint64) statfsbuf.f_blocks * (uint64) statfsbuf.f_bsize;
       freeSpace = (uint64) statfsbuf.f_bfree * (uint64) statfsbuf.f_bsize;
       destPtr += Str_Sprintf(destPtr, endDestPtr - destPtr,
-                             "<filesystem>"
-                             "<name>%s</name>"
-                             "<size>%"FMT64"u</size>"
-                             "<freeSpace>%"FMT64"u</freeSpace>"
-                             "<type>%s</type>"
-                             "</filesystem>",
+                             listFileSystemsFormatString,
                              MNTINFO_NAME(mnt),
                              size,
                              freeSpace,
@@ -3317,6 +3376,14 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN
 #endif
 
 abort:
+#if defined(_WIN32)
+   for (i = 0; i < numDrives; i++) {
+      Unicode_Free(driveList[i]);
+   }
+
+   free(driveList);
+#endif
+
    if (impersonatingVMWareUser) {
       VixToolsUnimpersonateUser(userToken);
    }
index 6199ab58567d966262e619f1f539bc72c2518afa..32393255f68fc2ae1eb57beef4de8b7ba8632228 100644 (file)
@@ -47,6 +47,7 @@
 #include "util.h"
 #include "str.h"
 #include "fileIO.h"
+#include "vmstdio.h"
 #include "mntinfo.h"
 #include "posix.h"
 
@@ -110,22 +111,113 @@ typedef struct WiperDiskString {
 } WiperDiskString;
 #endif
 
-#if defined(__linux__) && !defined(N_PLAT_NLM)
-static int dmNumEntries;
-static int dmNumbers[WIPER_MAX_DM_NUMBERS];
-#endif
-
 
 /* Variables */
 static Bool initDone = FALSE;
 
 
 /* Local functions */
-static INLINE Bool WiperIsDiskDevice(MNTINFO *mnt, struct stat *s);
+static Bool WiperIsDiskDevice(MNTINFO *mnt, struct stat *s);
 static void WiperPartitionFilter(WiperPartition *item, MNTINFO *mnt);
 static unsigned char *WiperGetSpace(WiperState *state, uint64 *free, uint64 *total);
 static void WiperClean(WiperState *state);
-static INLINE Bool WiperIsDeviceMapper(struct stat *s);
+
+
+#if defined(__linux__)
+
+#define MAX_DISK_MAJORS       256   /* should be enough for now */
+#define NUM_PRESEEDED_MAJORS  5     /* must match the below */
+
+static unsigned int knownDiskMajor[MAX_DISK_MAJORS] = {
+   /*
+    * Pre-seed some major numbers we were comparing against before
+    * we started scanning /proc/devices.
+    */
+   3,    /* First MFM, RLL and IDE hard disk/CD-ROM interface.
+            Inside a VM, this is simply the First IDE hard
+            disk/CD-ROM interface because we don't support
+            others */
+   8,    /* SCSI disk devices */
+   22,   /* Second IDE hard disk/CD-ROM interface */
+   43,   /* Network block device */
+   259,  /* Disks in 2.6.27 */
+};
+
+static int numDiskMajors;
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * WiperCollectDiskMajors --
+ *
+ *      Collects major numbers of devices that we considering "disks" and
+ *      may try to shrink.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      Populates knownDiskMajor array and numDiskMajors counter for
+ *      subsequent use by linux version of WiperIsDiskDevice().
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+WiperCollectDiskMajors(void)
+{
+   const char diskDevNames[] = "|ide0|ide1|sd|md|nbd|device-mapper|blkext|";
+   const char blockSeparator[] = "Block devices:";
+   Bool seenBlockSeparator = FALSE;
+   char *buf;
+   int major;
+   char device[64];
+   FILE *f;
+
+   numDiskMajors = NUM_PRESEEDED_MAJORS;
+
+   f = Posix_Fopen("/proc/devices", "r");
+   if (!f) {
+      return;
+   }
+
+   while (StdIO_ReadNextLine(f, &buf, 0, NULL) == StdIO_Success) {
+
+      if (!seenBlockSeparator) {
+         if (!memcmp(buf, blockSeparator, sizeof(blockSeparator) - 1)) {
+            seenBlockSeparator = TRUE;
+         }
+      } else if (sscanf(buf, "%d %61s\n", &major, device + 1) == 2) {
+
+         device[0] = '|';
+         device[sizeof(device) - 2] = '\0';
+         Str_Strcat(device, "|", sizeof(device));
+
+         if (strstr(diskDevNames, device)) {
+            knownDiskMajor[numDiskMajors++] = major;
+         }
+      }
+
+      free(buf);
+
+      if (numDiskMajors >= MAX_DISK_MAJORS) {
+         break;
+      }
+   }
+
+   fclose(f);
+}
+
+#else
+
+static void
+WiperCollectDiskMajors(void)
+{
+}
+
+#endif
+
 
 /*
  *-----------------------------------------------------------------------------
@@ -144,7 +236,7 @@ static INLINE Bool WiperIsDeviceMapper(struct stat *s);
  */
 
 #if defined(sun) /* SunOS { */
-static INLINE Bool
+static Bool
 WiperIsDiskDevice(MNTINFO *mnt,         // IN: file system being considered
                   struct stat *s)       // IN: stat(2) info of fs source
 {
@@ -185,30 +277,25 @@ WiperIsDiskDevice(MNTINFO *mnt,         // IN: file system being considered
 
 #elif defined(__linux__) /* } linux { */
 
-static INLINE Bool
+static Bool
 WiperIsDiskDevice(MNTINFO *mnt,         // IN: file system being considered
                   struct stat *s)       // IN: stat(2) info of fs source
 {
-   int majorN;
-
-   majorN = major(s->st_rdev);
-   if (! (   (majorN == 3)  /* First MFM, RLL and IDE hard disk/CD-ROM
-                              interface. Inside a VM, this is simply the First
-                              IDE hard disk/CD-ROM interface because we don't
-                              support others */
-             || (majorN == 22) /* Second IDE hard disk/CD-ROM interface */
-             || (majorN == 8)  /* SCSI disk devices */
-             || (majorN == 43) /* Network block device */
-             || (majorN == 259) /* Disks in 2.6.27 */)) {
-      return FALSE;
+   int majorN = major(s->st_rdev);
+   int i;
+
+   for (i = 0; i < numDiskMajors; i++) {
+      if (majorN == knownDiskMajor[i]) {
+         return TRUE;
+      }
    }
 
-   return TRUE;
+   return FALSE;
 }
 
 #elif defined(__FreeBSD__) || defined(__APPLE__) /* } FreeBSD { */
 
-static INLINE Bool
+static Bool
 WiperIsDiskDevice(MNTINFO *mnt,         // IN: file system being considered
                   struct stat *s)       // IN: stat(2) info of fs source
 {
@@ -338,11 +425,7 @@ WiperPartitionFilter(WiperPartition *item,         // IN/OUT
 #endif
 
    if (!WiperIsDiskDevice(mnt, &s)) {
-      if (WiperIsDeviceMapper(&s)) {
-         item->comment = WIPER_DEVICE_MAPPER_STRING;
-      } else {
-         item->comment = "Not a disk device";
-      }
+      item->comment = "Not a disk device";
       return;
    }
 
@@ -483,6 +566,7 @@ SingleWiperPartition_Open(const char *mountPoint)      // IN
             goto error;
          }
 
+         WiperCollectDiskMajors();
          WiperPartitionFilter(p, mnt);
          (void) CLOSE_MNTFILE(fp);
 
@@ -603,6 +687,8 @@ WiperPartition_Open(void)
       goto error;
    }
 
+   WiperCollectDiskMajors();
+
    while (GETNEXT_MNTINFO(fp, mnt)) {
       WiperPartition item;
 
@@ -996,73 +1082,6 @@ Wiper_Cancel(Wiper_State **s)      // IN/OUT
 Bool
 Wiper_Init(WiperInitData *clientData)
 {
-#if defined(__linux__) && !defined(N_PLAT_NLM)
-   FILE *fp;
-   int deviceNum;
-   char deviceName[256];
-
-   dmNumEntries = 0;
-   fp = Posix_Fopen("/proc/devices", "r");
-   if (fp) {
-      while (!feof(fp)) {
-         if (fscanf(fp, "%d %255s\n", &deviceNum, deviceName) == 2) {
-            if (Str_Strncmp(deviceName, "device-mapper", sizeof deviceName) == 0) {
-               dmNumbers[dmNumEntries++] = deviceNum;
-               if (dmNumEntries >= WIPER_MAX_DM_NUMBERS) {
-                  break;
-               }
-            }
-         } else if (fgets(deviceName, sizeof deviceName, fp) != deviceName) {
-            Warning("%s: Error reading device name from /proc/devices.", __func__);
-            break;
-         }
-      }
-
-      fclose(fp);
-   }
-#endif
-
    return initDone = TRUE;
 }
 
-
-/*
- *----------------------------------------------------------------------------
- *
- * WiperIsDeviceMapper --
- *
- *      Determines whether a partition's device id corresponds to
- *      the device-mapper device.
- *
- * Results:
- *      TRUE if the device number matches a device-mapper device number
- *      FALSE otherwise
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
-
-static INLINE Bool
-WiperIsDeviceMapper(struct stat *s)    // IN
-{
-#if defined(__linux__) && !defined(N_PLAT_NLM)
-   int majorNumber;
-   int i;
-
-   ASSERT(s);
-
-   majorNumber = major(s->st_rdev);
-
-   for (i = 0; i < dmNumEntries; ++i) {
-      if (majorNumber == dmNumbers[i]) {
-         return TRUE;
-      }
-   }
-
-   return FALSE;
-#else
-   return FALSE;
-#endif
-}
index 65d9d9a0a6e6fb8e635f95abca30e8c5d5818a0e..642c953b7f21cca138201819d57db03c0f00441a 100644 (file)
@@ -30,3 +30,19 @@ libguestlib_la_LDFLAGS =
 # We require GCC, so we're fine passing compiler-specific flags.
 # Needed for OS's that don't link shared libraries against libc by default, e.g. FreeBSD
 libguestlib_la_LDFLAGS += -Wl,-lc
+
+libguestlib_includedir = $(includedir)/vmGuestLib
+
+libguestlib_include_HEADERS =
+libguestlib_include_HEADERS += $(top_srcdir)/lib/include/includeCheck.h
+libguestlib_include_HEADERS += $(top_srcdir)/lib/include/vmGuestLib.h
+libguestlib_include_HEADERS += $(top_srcdir)/lib/include/vmSessionId.h
+libguestlib_include_HEADERS += $(top_srcdir)/lib/include/vm_basic_types.h
+
+EXTRA_DIST = vmguestlib.pc.in
+
+pkgconfigdir   = $(libdir)/pkgconfig
+pkgconfig_DATA = vmguestlib.pc
+
+$(pkgconfig_DATA): $(top_builddir)/config.status
+
diff --git a/open-vm-tools/libguestlib/vmguestlib.pc.in b/open-vm-tools/libguestlib/vmguestlib.pc.in
new file mode 100644 (file)
index 0000000..815d897
--- /dev/null
@@ -0,0 +1,11 @@
+# VMware GuestLib pkgconfig data.
+
+libdir=@libdir@
+includedir=@includedir@
+
+Name:          VMware GuestLib
+Description:   Library for retrieving information from VMware hosts.
+Version:       @VERSION@
+Libs:          -L${libdir} -lguestlib
+Cflags:        -I${includedir}/vmGuestLib
+
index b279d2c8dd543e2c0c717e4ae604bbb4da20168b..f41408f900121d12601ebf1df5a7c51e15a8df94 100644 (file)
@@ -241,7 +241,7 @@ VMTools_LoadConfig(const gchar *path,
       goto exit;
    }
 
-   if (!File_IsFile(path)) {
+   if (!File_IsFile(path) || File_GetSizeByPath(path) == 0) {
       goto exit;
    }
 
index 0d19328ffa38af676d5a62e4a09d2c0dac68f91b..cfe4d1fbce04afa1a400996f65a89ee1f4c40613 100644 (file)
@@ -333,8 +333,28 @@ HgfsReaddirInt(struct vnode *vp, // IN    : Directory vnode to get entries from.
       /* If the filename was too long, we skip to the next entry ... */
       if (ret == EOVERFLOW) {
          continue;
-      /* ... but if another error occurred, we return that error code ... */
+      } else if (ret == EBADF) {
+         /*
+          * If we got invalid handle from the server, this was because user
+          * enabled/disabled the shared folders. We should get a new handle
+          * from the server, now.
+          */
+         ret = HgfsRefreshHandle(vp, sip, &handle);
+         if (ret == 0) {
+            /*
+             * Now we have valid handle, let's try again from the same
+             * offset.
+             */
+            offset--;
+            continue;
+         } else {
+            ret = EBADF;
+            goto out;
+         }
       } else if (ret) {
+         if (ret != EPROTO) {
+            ret = EINVAL;
+         }
          DEBUG(VM_DEBUG_FAIL, "failure occurred in HgfsGetNextDirEntry\n");
          goto out;
       /*
@@ -348,13 +368,13 @@ HgfsReaddirInt(struct vnode *vp, // IN    : Directory vnode to get entries from.
          }
          break;
       }
-      /* 
+      /*
        * Convert an input string to utf8 decomposed form and then escape its
        * buffer.
        */
       ret = HgfsNameFromWireEncoding(nameBuf, strlen(nameBuf), dirp->d_name,
                                      sizeof dirp->d_name);
-      /* 
+      /*
        * If the name didn't fit in the buffer or illegal utf8 characters
        * were encountered, skip to the next entry.
        */
@@ -536,7 +556,7 @@ HgfsSetattrInt(struct vnode *vp,     // IN : vnode of the file
    reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request);
    reqBufferSize = HGFS_NAME_BUFFER_SIZET(reqSize);
 
-   /* 
+   /*
     * Convert an input string to utf8 precomposed form, convert it to
     * the cross platform name format and finally unescape any illegal
     * filesystem characters.
@@ -1644,11 +1664,11 @@ HgfsFileOpen(HgfsSuperInfo *sip,        // IN: Superinfo pointer
     * mainly implemented to address the issue with Mac OS. When the user
     * attempts to create a file in the root folder, the server returns ENOENT
     * error code. However, Mac OS specifically checks for this case. If Mac OS asks for
-    * the creation of a new file and if it gets ENOENT as a return error code, 
+    * the creation of a new file and if it gets ENOENT as a return error code,
     * then it assumes that the error was because of some race condition and tries it
     * again. Thus, returning ENOENT to the Mac OS puts the guest kernel into infinite
     * loop. In order to resolve this issue, before passing on the request to the
-    * server, we validate if user is attempting to create a new share. If yes, 
+    * server, we validate if user is attempting to create a new share. If yes,
     * we return EPERM as the error code.
     */
    if (HgfsAttemptToCreateShare(HGFS_VP_TO_FILENAME(vp), flag)) {
@@ -1730,17 +1750,29 @@ HgfsRefreshHandle(struct vnode *vp,          // IN: Vnode of file to open
    fp = HGFS_VP_TO_FP(vp);
    ASSERT(fp);
 
+   DEBUG(VM_DEBUG_ENTRY, "Refresh handle\n");
    os_rw_lock_lock_exclusive(fp->handleLock);
    if (fp->handle != *handle) {
       /* Handle has been refreshed in another thread. */
       *handle = fp->handle;
    } else {
       /* Retrieve a new handle from the host. */
-      ret = HgfsRequestHostFileHandle(sip, vp, (int *)&fp->mode, HGFS_OPEN, 0, handle);
+      if (HGFS_VP_TO_VTYPE(vp) == VREG) {
+         ret = HgfsRequestHostFileHandle(sip, vp, (int *)&fp->mode,
+                                         HGFS_OPEN, 0, handle);
+      } else if (HGFS_VP_TO_VTYPE(vp) == VDIR) {
+         char *fullPath = HGFS_VP_TO_FILENAME(vp);
+         uint32 fullPathLen = HGFS_VP_TO_FILENAME_LENGTH(vp);
+         ret = HgfsSendOpenDirRequest(sip, fullPath, fullPathLen, handle);
+      } else {
+         goto out;
+      }
       if (ret == 0) {
          fp->handle = *handle;
       }
    }
+
+out:
    os_rw_lock_unlock_exclusive(fp->handleLock);
 
    return ret;
@@ -2278,9 +2310,6 @@ HgfsGetNextDirEntry(HgfsSuperInfo *sip,         // IN: Superinfo pointer
    ret = HgfsGetStatus(req, sizeof *replyHeader);
    if (ret) {
       DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret);
-      if (ret != EPROTO) {
-         ret = EINVAL;
-      }
       goto destroyOut;
    }
 
@@ -2530,7 +2559,7 @@ HgfsSymlinkInt(struct vnode *dvp,         // IN : directory vnode
        * In the long term we should fix the protocol and have only one name
        * format which is suitable for all names.
        * The following code compensates for this problem before there is such
-       * universal name representation.  
+       * universal name representation.
        */
    if (*targetName == '/') {
       fileNameP->length = 1;
index bdf10da7048f9b47f75cf8770ba1da732ca57c75..664dc479e74603a723788eb14f2ea5756a5e0938 100644 (file)
@@ -1,23 +1,29 @@
 PACKAGE_NAME=open-vm-tools
-PACKAGE_VERSION=2009.06.18
-MAKE[0]="make -C pvscsi VM_UNAME=\$kernelver;   \
-         make -C vmblock VM_UNAME=\$kernelver;  \
-         make -C vmhgfs VM_UNAME=\$kernelver;   \
-         make -C vmmemctl VM_UNAME=\$kernelver; \
-         make -C vmsync VM_UNAME=\$kernelver;   \
-         make -C vmxnet VM_UNAME=\$kernelver;   \
-         make -C vsock VM_UNAME=\$kernelver;    \
-         make -C vmci VM_UNAME=\$kernelver;     \
-         make -C vmxnet3 VM_UNAME=\$kernelver"
-CLEAN[0]="make -C pvscsi clean;                 \
-          make -C vmblock clean;                \
-          make -C vmhgfs clean;                 \
-          make -C vmmemctl clean;               \
-          make -C vmsync clean;                 \
-          make -C vmxnet clean;                 \
-          make -C vsock clean;                  \
-          make -C vmci clean;                   \
-          make -C vmxnet3 clean"
+PACKAGE_VERSION=2009.07.22
+MAKE_CMD_TMPL="make VM_UNAME=\$kernelver \
+               MODULEBUILDDIR=$dkms_tree/$PACKAGE_NAME/$PACKAGE_VERSION/build"
+
+# The vsock module depends on symbols exported by the vmci module, so it
+# needs to be built afterwards; the MODULEBUILDDIR variable tells the makefiles
+# where to store / retrive those symbol files.
+MAKE[0]="$MAKE_CMD_TMPL -C pvscsi;     \
+         $MAKE_CMD_TMPL -C vmblock;    \
+         $MAKE_CMD_TMPL -C vmci;       \
+         $MAKE_CMD_TMPL -C vmhgfs;     \
+         $MAKE_CMD_TMPL -C vmmemctl;   \
+         $MAKE_CMD_TMPL -C vmsync;     \
+         $MAKE_CMD_TMPL -C vmxnet;     \
+         $MAKE_CMD_TMPL -C vmxnet3;    \
+         $MAKE_CMD_TMPL -C vsock"
+CLEAN[0]="$MAKE_CMD_TMPL -C pvscsi clean;     \
+          $MAKE_CMD_TMPL -C vmblock clean;    \
+          $MAKE_CMD_TMPL -C vmci clean;       \
+          $MAKE_CMD_TMPL -C vmhgfs clean;     \
+          $MAKE_CMD_TMPL -C vmmemctl clean;   \
+          $MAKE_CMD_TMPL -C vmsync clean";    \
+          $MAKE_CMD_TMPL -C vmxnet clean;     \
+          $MAKE_CMD_TMPL -C vmxnet3 clean;    \
+          $MAKE_CMD_TMPL -C vsock clean
 BUILT_MODULE_NAME[0]="pvscsi"
 BUILT_MODULE_NAME[1]="vmblock"
 BUILT_MODULE_NAME[2]="vmci"
diff --git a/open-vm-tools/modules/linux/dkms.sh b/open-vm-tools/modules/linux/dkms.sh
new file mode 100644 (file)
index 0000000..4513e8e
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/sh
+################################################################################
+### Copyright 2009 VMware, Inc.  All rights reserved.
+###
+### Script for creating a dmks-compliant source tree from an open-vm-tools
+### distribution.
+###
+###
+### 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
+################################################################################
+
+if test -z "$1" -o -z "$2"
+then
+   echo "usage: $0 src dst"
+   echo
+   echo "Where:"
+   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 2009.07.22."
+   exit 1
+fi
+
+src=$1
+dst=$2/open-vm-tools-2009.07.22
+
+SHARED_HEADERS="backdoor_def.h"
+SHARED_HEADERS="$SHARED_HEADERS backdoor_types.h"
+SHARED_HEADERS="$SHARED_HEADERS circList.h"
+SHARED_HEADERS="$SHARED_HEADERS dbllnklst.h"
+SHARED_HEADERS="$SHARED_HEADERS guest_msg_def.h"
+SHARED_HEADERS="$SHARED_HEADERS includeCheck.h"
+SHARED_HEADERS="$SHARED_HEADERS vm_assert.h"
+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_defs.h"
+SHARED_HEADERS="$SHARED_HEADERS vm_basic_math.h"
+SHARED_HEADERS="$SHARED_HEADERS vm_basic_types.h"
+SHARED_HEADERS="$SHARED_HEADERS vm_device_version.h"
+SHARED_HEADERS="$SHARED_HEADERS vmci_sockets.h"
+SHARED_HEADERS="$SHARED_HEADERS vmware.h"
+SHARED_HEADERS="$SHARED_HEADERS vmware_pack_begin.h"
+SHARED_HEADERS="$SHARED_HEADERS vmware_pack_end.h"
+SHARED_HEADERS="$SHARED_HEADERS vmware_pack_init.h"
+SHARED_HEADERS="$SHARED_HEADERS x86cpuid.h"
+
+rm -rf $dst
+mkdir -p $dst
+cp -f `dirname $0`/dkms.conf $dst
+
+for m in pvscsi vmblock vmci vmhgfs vmmemctl vmsync vmxnet vmxnet3 vsock
+do
+   mdst="$dst/$m"
+
+   cp -rf $src/modules/linux/$m $mdst
+   cp -rf $src/modules/linux/shared $mdst
+   for h in $SHARED_HEADERS
+   do
+      cp -f $src/lib/include/$h $mdst/shared
+   done
+
+   # Shared vmblock code.
+   if test $m = vmblock
+   then
+      cp -f $src/lib/include/vmblock.h $mdst/linux
+      cp -f $src/lib/misc/dbllnklst.c $mdst/linux
+      cp -rf $src/modules/shared/vmblock/* $mdst/linux
+   fi
+
+   # Backdoor library (for vmhgfs and vmmemctl).
+   if test $m = vmhgfs -o $m = vmmemctl
+   then
+      cp -f $src/lib/include/backdoor.h $mdst
+      cp -f $src/lib/backdoor/*.c $src/lib/backdoor/*.h $mdst
+   fi
+
+   # Other libraries used by vmhgfs
+   if test $m = vmhgfs
+   then
+      cp -f $src/lib/include/cpName*.h $mdst
+      cp -f $src/lib/include/escBitvector.h $mdst
+      cp -f $src/lib/include/hgfs*.h $mdst
+      cp -f $src/lib/include/message.h $mdst
+      cp -f $src/lib/include/rpcout.h $mdst
+      cp -f $src/lib/hgfs/*.c $src/lib/hgfs/*.h $mdst
+      cp -f $src/lib/hgfsBd/*.c $mdst
+      cp -f $src/lib/message/*.c $mdst
+      cp -f $src/lib/rpcOut/*.c $mdst
+   fi
+
+   # Extra header file for vmsync.
+   if test $m = vmsync
+   then
+      cp -f $src/lib/include/syncDriverIoc.h $mdst
+   fi
+
+   # Shared vmxnet / vmxnet3 headers.
+   if test $m = vmxnet -o $m = vmxnet3
+   then
+      cp -f $src/modules/shared/vmxnet/* $mdst/shared
+   fi
+done
+
index ed6ffca304cd2c35875394c1f27c490ddfa30a28..642f013404b6d1063f96ad970be9e7656819434f 100644 (file)
 #define SCSI_ASC_WRITE_ERROR                                    0x0c  // Write error
 #define SCSI_ASC_UNRECOVERED_READ_ERROR                         0x11  // Unrecovered read error
 #define SCSI_ASC_PARAM_LIST_LENGTH_ERROR                        0x1a  // parameter list length error
+#define SCSI_ASC_RECOVERED_DATA                                 0x17
 #define SCSI_ASC_INVALID_COMMAND_OPERATION                     0x20  // invalid command operation code
 #define SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE             0x21  // Invalid LBA
 #define SCSI_ASC_INVALID_FIELD_IN_CDB                           0x24
@@ -410,7 +411,9 @@ typedef struct {
          w32        :1,   // device supports 32-bit wide SCSI data transfers
         rel         :1;   // device supports relative addressing
    uint8 manufacturer[8];  // manufacturer's name in ascii
+#define SCSI_VENDOR_SZ sizeof(((SCSIInquiryResponse *) 0)->manufacturer)
    uint8 product[16];     // product name in ascii
+#define SCSI_MODEL_SZ sizeof(((SCSIInquiryResponse *) 0)->product)
    uint8 revision[4];     // product version number in ascii
    uint8 vendor1[20];     // vendor unique data (opaque)
    uint8 reserved[40];
index 22454149755e0f4d0a898a5d852df00bf55a75f2..b6912501628a107822bfe5cb3c681efbe1780a7c 100644 (file)
 #include <linux/stddef.h> /* for NULL */
 #include <net/sock.h>
 
-
 /*
  * Between 2.5.70 and 2.5.71 all sock members were renamed from XXX to sk_XXX.
- *
- * VMW_HAVE_SK_WMEM_ALLOC is defined in module Makefile if kernel's struct sock
- * has sk_wmem_alloc member. See vmnet's Makefile.kernel for details.
- * It also means that all modules including this file should do
- *
- * EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/socket.c,  -DVMW_HAVE_SK_WMEM_ALLOC, )
- *
- * in their Makefiles.
  */
-#ifndef VMW_HAVE_SK_WMEM_ALLOC
-#   define sk_wmem_alloc wmem_alloc
-#endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 71)
 # define compat_sk_backlog_rcv          backlog_rcv
index 1f268534a1e19205a7edde2a7c1b4d75e8b6954d..198f4daf185859039cf84194a2c5737aa739deb7 100644 (file)
@@ -289,15 +289,25 @@ int VMCI_PopulatePPNList(uint8 *callBuf, const PPNSet *ppnSet);
 struct PageStoreAttachInfo;
 struct VMCIQueue;
 
-int VMCIHost_GetUserMemory(struct PageStoreAttachInfo *attach);
-void VMCIHost_ReleaseUserMemory(struct PageStoreAttachInfo *attach);
-int VMCIHost_FinishAttach(struct PageStoreAttachInfo *attach,
-                          struct VMCIQueue *produceQ,
-                         struct VMCIQueue *detachQ);
-void VMCIHost_DetachMappings(struct PageStoreAttachInfo *attach,
-                             struct VMCIQueue *produceQ,
-                             struct VMCIQueue *detachQ);
-#endif
+int VMCIHost_GetUserMemory(struct PageStoreAttachInfo *attach,
+                           struct VMCIQueue *produceQ,
+                           struct VMCIQueue *detachQ);
+void VMCIHost_ReleaseUserMemory(struct PageStoreAttachInfo *attach,
+                                struct VMCIQueue *produceQ,
+                                struct VMCIQueue *detachQ);
+
+#ifdef _WIN32
+/*
+ * Special routine used on the Windows platform to save a queue when
+ * its backing memory goes away.
+ */
+
+void VMCIHost_SaveProduceQ(struct PageStoreAttachInfo *attach,
+                           struct VMCIQueue *produceQ,
+                           struct VMCIQueue *detachQ,
+                           const uint64 produceQSize);
+#endif // _WIN32
+#endif // !VMX86_TOOLS && !VMKERNEL
 
 
 #endif // _VMCI_KERNEL_IF_H_
index c1a1fc5bcce3c2604d2f005e5adf2874269a5a27..be69c284e861b26daaa6bd8725c4355685476ea7 100644 (file)
@@ -65,8 +65,42 @@ struct page;
 
 
 /*
+ * VMCIQueueHeader
+ *
+ * A Queue cannot stand by itself as designed.  Each Queue's header
+ * contains a pointer into itself (the producerTail) and into its peer
+ * (consumerHead).  The reason for the separation is one of
+ * accessibility: Each end-point can modify two things: where the next
+ * location to enqueue is within its produceQ (producerTail); and
+ * where the next location in its consumeQ (i.e., its peer's produceQ)
+ * it can dequeue (consumerHead).  The end-point cannot modify the
+ * pointers of its peer (guest to guest; NOTE that in the host both
+ * queue headers are mapped r/w).  But, each end-point needs access to
+ * both Queue header structures in order to determine how much space
+ * is used (or left) in the Queue.  This is because for an end-point
+ * to know how full its produceQ is, it needs to use the consumerHead
+ * that points into the produceQ but -that- consumerHead is in the
+ * Queue header for that end-points consumeQ.
+ *
+ * Thoroughly confused?  Sorry.
+ *
+ * producerTail: the point to enqueue new entrants.  When you approach
+ * a line in a store, for example, you walk up to the tail.
+ *
+ * consumerHead: the point in the queue from which the next element is
+ * dequeued.  In other words, who is next in line is he who is at the
+ * head of the line.
+ *
+ * Also, producerTail points to an empty byte in the Queue, whereas
+ * consumerHead points to a valid byte of data (unless producerTail ==
+ * consumerHead in which case consumerHead does not point to a valid
+ * byte of data).
+ *
  * For a queue of buffer 'size' bytes, the tail and head pointers will be in
  * the range [0, size-1].
+ *
+ * If produceQ->producerTail == consumeQ->consumerHead then the
+ * produceQ is empty.
  */
 
 typedef struct VMCIQueueHeader {
@@ -281,15 +315,78 @@ AddPointer(Atomic_uint64 *var, // IN:
        * Also, the queue contents are managed by an array of bytes
        * which are managed elsewhere.  So, this structure simply
        * contains the address of that array of bytes.
+       *
+       * We have a mutex to protect the queue from accesses within the
+       * kernel module.  NOTE: the guest may be enqueuing or dequeuing
+       * while the host has the mutex locked.  However, multiple
+       * kernel processes will not access the Queue simultaneously.
+       *
+       * What the mutex is trying to protect is the moment where the
+       * guest detaches from a queue.  In that moment, we will
+       * allocate memory to hold the guest's produceQ and we will
+       * change the queueHeaderPtr to point to a newly allocated (in
+       * kernel memory) structure.  And, the buffer pointer will be
+       * changed to point to an in-kernel queue content (even if there
+       * isn't any data in the queue for the host to consume).
+       *
+       * Note that a VMCIQueue allocated by the host passes through
+       * three states before it's torn down.  First, the queue is
+       * created by the host but doesn't point to any memory and
+       * therefore can't absorb any enqueue requests.  (NOTE: On
+       * Windows this could be solved because of the mutexes, as
+       * explained above [only in reverse, if you will].  But unless
+       * we added the same mutexes [or other rules about accessing the
+       * queues] we can't can't solve this generally on other
+       * operating systems.)
+       *
+       * When the guest calls SetPageStore(), then the queue is backed
+       * by valid memory and the host can enqueue.
+       *
+       * When the guest detaches, enqueues are absorbed by /dev/null,
+       * as it were.
        */
       typedef struct VMCIQueue {
         VMCIQueueHeader *queueHeaderPtr;
         uint8 *buffer;
+         Bool enqueueToDevNull;
+         FAST_MUTEX *mutex;    /* Access the mutex through this */
+         FAST_MUTEX __mutex;   /* Don't touch except to init */
       } VMCIQueue;
+#define VMCIQueuePair_EnqueueToDevNull(q)      ((q)->enqueueToDevNull)
 #define VMCIQueuePair_QueueIsMapped(q)          ((q)->buffer != NULL)
 #  endif
 #endif
 
+#ifndef VMCIQueuePair_EnqueueToDevNull
+#define VMCIQueuePair_EnqueueToDevNull(q)       (FALSE)
+#endif /* default VMCIQueuePair_EnqueueToDevNull() definition */
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMCIMemcpy{To,From}QueueFunc() prototypes.  Functions of these
+ * types are passed around to enqueue and dequeue routines.  Note that
+ * often the functions passed are simply wrappers around memcpy
+ * itself.
+ *
+ *-----------------------------------------------------------------------------
+ */
+typedef int VMCIMemcpyToQueueFunc(VMCIQueue *queue, uint64 queueOffset,
+                                  const void *src, size_t srcOffset,
+                                  size_t size);
+typedef int VMCIMemcpyFromQueueFunc(void *dest, size_t destOffset,
+                                    const VMCIQueue *queue, uint64 queueOffset,
+                                    size_t size);
+
+/*
+ * NOTE: On Windows host we have special code to access the queue
+ * contents (and QueuePair header) so that we can protect accesses
+ * during tear down of the guest that owns the mappings of the
+ * QueuePair queue contents.  See
+ * bora/modules/vmcrosstalk/windows/vmciHostQueuePair.c
+ */
+
+#if !defined _WIN32 || defined VMX86_TOOLS || defined VMX86_VMX
 
 /*
  *-----------------------------------------------------------------------------
@@ -430,23 +527,6 @@ VMCIQueue_AddConsumerHead(VMCIQueue *queue,
 }
 
 
-/*
- *-----------------------------------------------------------------------------
- *
- * VMCIMemcpy{To,From}QueueFunc() prototypes.  Functions of these
- * types are passed around to enqueue and dequeue routines.  Note that
- * often the functions passed are simply wrappers around memcpy
- * itself.
- *
- *-----------------------------------------------------------------------------
- */
-typedef int VMCIMemcpyToQueueFunc(VMCIQueue *queue, uint64 queueOffset,
-                                  const void *src, size_t srcOffset,
-                                  size_t size);
-typedef int VMCIMemcpyFromQueueFunc(void *dest, size_t destOffset,
-                                    const VMCIQueue *queue, uint64 queueOffset,
-                                    size_t size);
-
 /*
  *-----------------------------------------------------------------------------
  *
@@ -825,6 +905,10 @@ __VMCIQueue_Enqueue(VMCIQueue *produceQueue,               // IN:
    uint64 tail;
    size_t written;
 
+   if (UNLIKELY(VMCIQueuePair_EnqueueToDevNull(produceQueue))) {
+      return bufSize;
+   }
+
    if (UNLIKELY(!VMCIQueuePair_QueueIsMapped(produceQueue) &&
                !VMCIQueuePair_QueueIsMapped(consumeQueue))) {
       return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
@@ -920,7 +1004,7 @@ VMCIQueue_EnqueueV(VMCIQueue *produceQueue,       // IN:
    return __VMCIQueue_Enqueue(produceQueue, consumeQueue, produceQSize,
                               (void *)iov, iovSize, VMCIMemcpyToQueueV);
 }
-#endif
+#endif /* Systems that support struct iovec */
 
 
 /*
@@ -1055,7 +1139,7 @@ VMCIQueue_DequeueV(VMCIQueue *produceQueue,       // IN:
    return __VMCIQueue_Dequeue(produceQueue, consumeQueue, consumeQSize,
                               (void *)iov, iovSize, VMCIMemcpyFromQueueV, TRUE);
 }
-#endif
+#endif /* Systems that support struct iovec */
 
 
 /*
@@ -1124,6 +1208,42 @@ VMCIQueue_PeekV(VMCIQueue *produceQueue,       // IN:
    return __VMCIQueue_Dequeue(produceQueue, consumeQueue, consumeQSize,
                               (void *)iov, iovSize, VMCIMemcpyFromQueueV, FALSE);
 }
-#endif
+#endif /* Systems that support struct iovec */
+
+#else /* Windows 32 Host defined below */
+
+int VMCIMemcpyToQueue(VMCIQueue *queue, uint64 queueOffset, const void *src,
+                      size_t srcOffset, size_t size);
+int VMCIMemcpyFromQueue(void *dest, size_t destOffset, const VMCIQueue *queue,
+                        uint64 queueOffset, size_t size);
+
+void VMCIQueue_Init(const VMCIHandle handle, VMCIQueue *queue);
+void VMCIQueue_GetPointers(const VMCIQueue *produceQ,
+                           const VMCIQueue *consumeQ,
+                           uint64 *producerTail,
+                           uint64 *consumerHead);
+int64 VMCIQueue_FreeSpace(const VMCIQueue *produceQueue,
+                          const VMCIQueue *consumeQueue,
+                          const uint64 produceQSize);
+int64 VMCIQueue_BufReady(const VMCIQueue *consumeQueue,
+                         const VMCIQueue *produceQueue,
+                         const uint64 consumeQSize);
+ssize_t VMCIQueue_Enqueue(VMCIQueue *produceQueue,
+                          const VMCIQueue *consumeQueue,
+                          const uint64 produceQSize,
+                          const void *buf,
+                          size_t bufSize);
+ssize_t VMCIQueue_Dequeue(VMCIQueue *produceQueue,
+                          const VMCIQueue *consumeQueue,
+                          const uint64 consumeQSize,
+                          void *buf,
+                          size_t bufSize);
+ssize_t VMCIQueue_Peek(VMCIQueue *produceQueue,
+                       const VMCIQueue *consumeQueue,
+                       const uint64 consumeQSize,
+                       void *buf,
+                       size_t bufSize);
+
+#endif /* defined _WIN32 && !defined VMX86_TOOLS */
 
 #endif /* !_PUBLIC_VMCI_QUEUE_PAIR_H_ */
index 9e7d3360ac9fde62c4619e09ccf8ec5d88ccd693..cc2de6acc10ed04f124f51aa22af31501f3ea723 100644 (file)
@@ -1394,95 +1394,6 @@ VMCIWellKnownID_AllowMap(VMCIId wellKnownID,           // IN:
 
 #ifndef VMX86_TOOLS
 
-/*
- *-----------------------------------------------------------------------------
- *
- * VMCIHost_FinishAttach --
- *       Finish the "attach" operation by update the queues to be
- *       backed by the shared memory represented by the "attach"
- *       structure.
- *
- * Results:
- *       VMCI_SUCCESS on success or negative error on failure.
- *
- * Side Effects:
- *       None
- *
- *-----------------------------------------------------------------------------
- */
-
-int
-VMCIHost_FinishAttach(PageStoreAttachInfo *attach,      // IN
-                      VMCIQueue *produceQ,              // OUT
-                      VMCIQueue *consumeQ)              // OUT
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-   produceQ->queueHeaderPtr = kmap(attach->producePages[0]);
-   produceQ->page = &attach->producePages[1];
-   consumeQ->queueHeaderPtr = kmap(attach->consumePages[0]);
-   consumeQ->page = &attach->consumePages[1];
-#else
-   /*
-    * Host queue pair support for earlier kernels temporarily
-    * disabled. See bug 365496.
-    */
-
-   ASSERT_NOT_IMPLEMENTED(FALSE);
-#if 0 
-   produceQ->queueHeaderPtr = kmap(attach->produceIoBuf->maplist[0]);
-   produceQ->page = &attach->produceIoBuf->maplist[1];
-   consumeQ->queueHeaderPtr = kmap(attach->consumeIoBuf->maplist[0]);
-   consumeQ->page = &attach->consumeIoBuf->maplist[1];
-#endif
-#endif
-
-   return VMCI_SUCCESS;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * VMCIHost_DetachMappings --
- *       Remove any local mappings of memory referenced in 'attach' in
- *       preparation for releasing the shared memory region entirely.
- *
- * Results:
- *       None.
- *
- * Side Effects:
- *       None.
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-VMCIHost_DetachMappings(struct PageStoreAttachInfo *attach,
-                        struct VMCIQueue *produceQ,
-                        struct VMCIQueue *detachQ)
-{
-   /*
-    * Unmap the header pages
-    */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-   kunmap(attach->producePages[0]);
-   kunmap(attach->consumePages[0]);
-#else
-   /*
-    * Host queue pair support for earlier kernels temporarily
-    * disabled. See bug 365496.
-    */
-
-   ASSERT_NOT_IMPLEMENTED(FALSE);
-#if 0
-   kunmap(attach->produceIoBuf->maplist[0]);
-   kunmap(attach->consumeIoBuf->maplist[0]);
-#endif
-#endif
-}
-
-
 /*
  *-----------------------------------------------------------------------------
  *
@@ -1501,7 +1412,9 @@ VMCIHost_DetachMappings(struct PageStoreAttachInfo *attach,
  */
 
 int
-VMCIHost_GetUserMemory(PageStoreAttachInfo *attach)         // IN/OUT
+VMCIHost_GetUserMemory(PageStoreAttachInfo *attach,      // IN/OUT
+                       VMCIQueue *produceQ,              // OUT
+                       VMCIQueue *consumeQ)              // OUT
 {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    int retval;
@@ -1563,6 +1476,13 @@ VMCIHost_GetUserMemory(PageStoreAttachInfo *attach)         // IN/OUT
       err = VMCI_ERROR_NO_MEM;
    }
 
+   if (err == VMCI_SUCCESS) {
+      produceQ->queueHeaderPtr = kmap(attach->producePages[0]);
+      produceQ->page = &attach->producePages[1];
+      consumeQ->queueHeaderPtr = kmap(attach->consumePages[0]);
+      consumeQ->page = &attach->consumePages[1];
+   }
+
 out:
    up_write(&current->mm->mmap_sem);
 
@@ -1620,6 +1540,13 @@ errorDealloc:
       err = VMCI_ERROR_NO_ACCESS;
    }
 
+   if (err == VMCI_SUCCESS) {
+      produceQ->queueHeaderPtr = kmap(attach->produceIoBuf->maplist[0]);
+      produceQ->page = &attach->produceIoBuf->maplist[1];
+      consumeQ->queueHeaderPtr = kmap(attach->consumeIoBuf->maplist[0]);
+      consumeQ->page = &attach->consumeIoBuf->maplist[1];
+   }
+
 out:
 
    if (err < VMCI_SUCCESS) {
@@ -1632,11 +1559,12 @@ out:
                             sizeof *attach->consumeIoBuf);
       }
    }
+
    return err;
-#else
+#else // 0 -- Instead just return FALSE
    return FALSE;
-#endif
-#endif
+#endif // 0
+#endif // Linux version >= 2.6.0
 }
 
 
@@ -1658,7 +1586,9 @@ out:
  */
 
 void
-VMCIHost_ReleaseUserMemory(PageStoreAttachInfo *attach)         // IN
+VMCIHost_ReleaseUserMemory(PageStoreAttachInfo *attach,      // IN/OUT
+                           VMCIQueue *produceQ,              // OUT
+                           VMCIQueue *consumeQ)              // OUT
 {
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
@@ -1666,6 +1596,10 @@ VMCIHost_ReleaseUserMemory(PageStoreAttachInfo *attach)         // IN
 
    ASSERT(attach->producePages);
    ASSERT(attach->consumePages);
+
+   kunmap(attach->producePages[0]);
+   kunmap(attach->consumePages[0]);
+
    for (i = 0; i < attach->numProducePages; i++) {
       ASSERT(attach->producePages[i]);
 
@@ -1694,6 +1628,9 @@ VMCIHost_ReleaseUserMemory(PageStoreAttachInfo *attach)         // IN
 
    ASSERT_NOT_IMPLEMENTED(FALSE);
 #if 0
+   kunmap(attach->produceIoBuf->maplist[0]);
+   kunmap(attach->consumeIoBuf->maplist[0]);
+
    mark_dirty_kiobuf(attach->produceIoBuf,
                      attach->numProducePages * PAGE_SIZE);
    unmap_kiobuf(attach->produceIoBuf);
index 1fa9840a012a864f20ba0c79936a299b2bb89dfb..0111e4df596e4e9779d5f07cca75f2c249c71f18 100644 (file)
@@ -160,11 +160,10 @@ HgfsBdChannelSend(HgfsTransportChannel *channel, // IN: Channel
    ret = HgfsBd_Dispatch(channel->priv, HGFS_REQ_PAYLOAD(req), &payloadSize,
                          &replyPacket);
    if (ret == 0) {
+      LOG(8, ("VMware hgfs: %s: Backdoor reply received.\n", __func__));
       /* Request sent successfully. Copy the reply and wake the client. */
       ASSERT(replyPacket);
       HgfsCompleteReq(req, replyPacket, payloadSize);
-      LOG(8, (KERN_DEBUG "VMware hgfs: HgfsSendUnsentReqs: Backdoor "
-              "reply received\n"));
    } else {
       channel->priv = NULL;
       channel->status = HGFS_CHANNEL_NOTCONNECTED;
index cbb80d77d6524f210d329ff9d9440fa6c884abd1..344e789078f7cbd1c5b0a7b70535ce042d850461 100644 (file)
@@ -73,6 +73,7 @@ HgfsGetNewRequest(void)
               "can't allocate memory\n"));
       return NULL;
    }
+   INIT_LIST_HEAD(&req->list);
    init_waitqueue_head(&req->queue);
    req->payloadSize = 0;
    req->state = HGFS_REQ_STATE_ALLOCATED;
index 4ed83a16f8109ac3935ab7d3bce402d2ef8d4cb9..82743a104a46d7af3b74c3f31ac6c53efd025cc8 100644 (file)
@@ -277,17 +277,15 @@ HgfsTcpConnect(HgfsTransportChannel *channel)
    addr.sin_addr.s_addr = in_aton(HOST_IP);
    addr.sin_port = htons(HOST_PORT);
 
-   error = compat_sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP,
-                                   &sock);
+   error = compat_sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
    if (error >= 0) {
       error = sock->ops->connect(sock, (struct sockaddr *)&addr,
                                  sizeof addr, 0);
       if (error >= 0) {
          channel->priv = sock;
-
          /* Reset receive buffer when a new connection is connected. */
-         recvBuffer.state = HGFS_TCP_CONN_RECV_HEADER;
-
+         HgfsTcpResetRecvBuffer();
+         sock->sk->compat_sk_rcvtimeo = HGFS_SOCKET_RECV_TIMEOUT * HZ;
          channel->status = HGFS_CHANNEL_CONNECTED;
          LOG(8, ("%s: tcp channel connected.\n", __func__));
          ret = TRUE;
@@ -336,18 +334,15 @@ HgfsVSocketConnect(HgfsTransportChannel *channel)
    addr.svm_cid = VMCI_HOST_CONTEXT_ID;
    addr.svm_port = HOST_VSOCKET_PORT;
 
-   error = compat_sock_create_kern(family, SOCK_STREAM, 0,
-                                   &sock);
+   error = compat_sock_create_kern(family, SOCK_STREAM, 0, &sock);
    if (error >= 0) {
       error = sock->ops->connect(sock, (struct sockaddr *)&addr,
                                  sizeof addr, 0);
       if (error >= 0) {
          channel->priv = sock;
-
          /* Reset receive buffer when a new connection is connected. */
          HgfsTcpResetRecvBuffer();
          sock->sk->compat_sk_rcvtimeo = HGFS_SOCKET_RECV_TIMEOUT * HZ;
-
          channel->status = HGFS_CHANNEL_CONNECTED;
          LOG(8, ("%s: vsocket channel connected.\n", __func__));
          ret = TRUE;
index e1cecce52e203cc4cf63fff9e7a206be0a67990e..a8e040271821fade6e00ac0a60c19496b082e092 100644 (file)
@@ -878,6 +878,21 @@ static int
 vmxnet_probe_device(struct pci_dev             *pdev, // IN: vmxnet PCI device
                     const struct pci_device_id *id)   // IN: matching device ID
 {
+#ifdef HAVE_NET_DEVICE_OPS
+   static const struct net_device_ops vmxnet_netdev_ops = {
+      .ndo_open = &vmxnet_open,
+      .ndo_start_xmit = &vmxnet_start_tx,
+      .ndo_stop = &vmxnet_close,
+      .ndo_get_stats = &vmxnet_get_stats,
+      .ndo_set_multicast_list = &vmxnet_set_multicast_list,
+      .ndo_change_mtu = &vmxnet_change_mtu,
+#   ifdef VMW_HAVE_POLL_CONTROLLER
+      .ndo_poll_controller = vmxnet_netpoll,
+#   endif
+      .ndo_set_mac_address = &vmxnet_set_mac_address,
+      .ndo_tx_timeout = &vmxnet_tx_timeout,
+   };
+#endif /* HAVE_NET_DEVICE_OPS */
    struct Vmxnet_Private *lp;
    struct net_device *dev;
    unsigned int ioaddr, reqIOAddr, reqIOSize;
@@ -982,6 +997,9 @@ vmxnet_probe_device(struct pci_dev             *pdev, // IN: vmxnet PCI device
 
    dev->irq = irq_line;
 
+#ifdef HAVE_NET_DEVICE_OPS
+   dev->netdev_ops = &vmxnet_netdev_ops;
+#else
    dev->open = &vmxnet_open;
    dev->hard_start_xmit = &vmxnet_start_tx;
    dev->stop = &vmxnet_close;
@@ -992,14 +1010,17 @@ vmxnet_probe_device(struct pci_dev             *pdev, // IN: vmxnet PCI device
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43)
    dev->tx_timeout = &vmxnet_tx_timeout;
-   dev->watchdog_timeo = VMXNET_WATCHDOG_TIMEOUT;
 #endif
 #ifdef VMW_HAVE_POLL_CONTROLLER
    dev->poll_controller = vmxnet_netpoll;
 #endif
-
    /* Do this after ether_setup(), which sets the default value. */
    dev->set_mac_address = &vmxnet_set_mac_address;
+#endif /* HAVE_NET_DEVICE_OPS */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43)
+   dev->watchdog_timeo = VMXNET_WATCHDOG_TIMEOUT;
+#endif
 
 #ifdef SET_ETHTOOL_OPS
    SET_ETHTOOL_OPS(dev, &vmxnet_ethtool_ops);
index 30d033005d4e0ff344d7610a70516a28eb34bf1b..dd6922d75145058ca0fad0acc5e8d3dfb3bd42f6 100644 (file)
@@ -34,6 +34,8 @@ EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/netif_num_params.c, , -DV
 
 obj-m += $(DRIVER).o
 
+$(DRIVER)-y := $(subst $(SRCROOT)/, , $(patsubst %.c, %.o, $(wildcard $(SRCROOT)/*.c)))
+
 clean:
        rm -rf $(wildcard $(DRIVER).mod.c $(DRIVER).ko .tmp_versions \
               Module.symvers Modules.symvers Module.markers modules.order \
similarity index 94%
rename from open-vm-tools/modules/linux/vmxnet3/vmxnet3.c
rename to open-vm-tools/modules/linux/vmxnet3/vmxnet3_drv.c
index b3bff15cec7b060de7c248fc58ad40deda4c08e6..57ef1627a3450e49bd5ca7c08799d4d58a935ec4 100644 (file)
@@ -38,6 +38,7 @@
 #include "compat_spinlock.h"
 #include "compat_ioport.h"
 #include "compat_pci.h"
+#include "compat_highmem.h"
 #include "compat_init.h"
 #include "compat_timer.h"
 #include "compat_netdevice.h"
@@ -48,6 +49,7 @@
 #include <asm/dma.h>
 #include <asm/page.h>
 #include <asm/uaccess.h>
+#include <linux/types.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/ip.h>
 #include "vm_device_version.h"
 #include "vmxnet3_version.h"
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && !defined(VMXNET3_NO_NAPI)
-#   define VMXNET3_NAPI
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
-#   define VMXNET3_NEW_NAPI
-#endif
-#endif
-
 #include "vmxnet3_int.h"
+#include "vmxnet3_shm.h"
 
 #ifdef VLAN_GROUP_ARRAY_SPLIT_PARTS
 #   define compat_vlan_group_get_device(vlan_grp, vid)       vlan_group_get_device(vlan_grp, vid)
 #   define compat_vlan_group_set_device(vlan_grp, vid, dev) ((vlan_grp)->vlan_devices[(vid)] = (dev))
 #endif
 
-#ifdef VMX86_DEBUG
-#   define VMXNET3_ASSERT(cond) BUG_ON(!(cond))
-#else
-#   define VMXNET3_ASSERT(cond) do {} while (0)
-#endif
-
-#ifdef VMXNET3_DO_LOG
-#   define VMXNET3_LOG(msg...) printk(KERN_ERR msg)
-#else
-#   define VMXNET3_LOG(msg...)
-#endif
 
 #ifdef VMXNET3_NAPI
 #   ifdef VMX86_DEBUG
@@ -156,6 +141,15 @@ static struct pci_driver vmxnet3_driver = {
 };
 
 static int disable_lro;
+static int devices_found;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)
+static unsigned int num_enable_shm;
+#endif
+#define VMXNET3_SHM_MAX_DEVICES 10
+static int enable_shm[VMXNET3_SHM_MAX_DEVICES + 1] =
+   { [0 ... VMXNET3_SHM_MAX_DEVICES] = -1 };
+static char *shm_disclaimer = NULL;
+#define VMXNET3_SHM_DISCLAIMER "IReallyWantThisModeIAmAVMSafePartner"
 
 /*
  *----------------------------------------------------------------------------
@@ -713,15 +707,16 @@ static void
 vmxnet3_map_pkt(struct sk_buff *skb,
                 struct vmxnet3_tx_ctx *ctx,
                 struct vmxnet3_tx_queue *tq,
-                struct pci_dev *pdev)
+                struct pci_dev *pdev,
+                struct vmxnet3_adapter *adapter)
 {
    uint32 dw2, len;
-   char *buf;
+   unsigned long buf_offset;
    int i;
    Vmxnet3_GenericDesc *gdesc;
    struct vmxnet3_tx_buf_info *tbi = NULL;
 
-   VMXNET3_ASSERT(ctx->copy_size <= compat_skb_headlen(skb));
+   VMXNET3_ASSERT(ctx->copy_size <= vmxnet3_skb_headlen(adapter, skb));
 
    /* use the previous gen bit for the SOP desc */
    dw2 = (tq->tx_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT;
@@ -751,8 +746,8 @@ vmxnet3_map_pkt(struct sk_buff *skb,
    }
 
    /* linear part can use multiple tx desc if it's big */
-   len = compat_skb_headlen(skb) - ctx->copy_size;
-   buf = skb->data + ctx->copy_size;
+   len = vmxnet3_skb_headlen(adapter, skb) - ctx->copy_size;
+   buf_offset = ctx->copy_size;
    while (len) {
       uint32 buf_size;
 
@@ -760,8 +755,9 @@ vmxnet3_map_pkt(struct sk_buff *skb,
 
       tbi = tq->buf_info + tq->tx_ring.next2fill;
       tbi->map_type = VMXNET3_MAP_SINGLE;
-      tbi->dma_addr = pci_map_single(pdev, buf,
-                                     buf_size, PCI_DMA_TODEVICE);
+      tbi->dma_addr = vmxnet3_map_single(adapter, skb, buf_offset,
+                                         buf_size, PCI_DMA_TODEVICE);
+
       tbi->len = buf_size; /* this automatically convert 2^14 to 0 */
 
       gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
@@ -777,7 +773,15 @@ vmxnet3_map_pkt(struct sk_buff *skb,
       dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
 
       len -= buf_size;
-      buf += buf_size;
+      buf_offset += buf_size;
+
+      if (adapter->is_shm) {
+         /*
+          * The linear region of the skb is never larger than a page, so
+          * it always fits into one descriptor.
+          */
+         VMXNET3_ASSERT(len == 0);
+      }
    }
 
    for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@ -785,8 +789,10 @@ vmxnet3_map_pkt(struct sk_buff *skb,
 
       tbi = tq->buf_info + tq->tx_ring.next2fill;
       tbi->map_type = VMXNET3_MAP_PAGE;
-      tbi->dma_addr = pci_map_page(pdev, frag->page, frag->page_offset,
-                                   frag->size, PCI_DMA_TODEVICE);
+      tbi->dma_addr = vmxnet3_map_page(adapter, frag->page,
+                                       frag->page_offset,
+                                       frag->size, PCI_DMA_TODEVICE);
+
       tbi->len = frag->size;
 
       gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
@@ -838,7 +844,8 @@ vmxnet3_map_pkt(struct sk_buff *skb,
 static int
 vmxnet3_parse_and_copy_hdr(struct sk_buff *skb,
                            struct vmxnet3_tx_queue *tq,
-                           struct vmxnet3_tx_ctx *ctx)
+                           struct vmxnet3_tx_ctx *ctx,
+                           struct vmxnet3_adapter *adapter)
 {
    Vmxnet3_TxDataDesc *tdd;
 
@@ -871,15 +878,18 @@ vmxnet3_parse_and_copy_hdr(struct sk_buff *skb,
          }
          ctx->copy_size = ctx->eth_ip_hdr_size + ctx->l4_hdr_size;
       } else {
-         ctx->eth_ip_hdr_size = 14;
+         ctx->eth_ip_hdr_size = 0;
          ctx->l4_hdr_size = 0;
          /* copy as much as allowed */
-         ctx->copy_size = min((unsigned int)VMXNET3_HDR_COPY_SIZE, skb_headlen(skb));
+         ctx->copy_size = min((unsigned int)VMXNET3_HDR_COPY_SIZE,
+                              vmxnet3_skb_headlen(adapter, skb));
       }
 
-      /* make sure headers are accessible directly */
-      if (UNLIKELY(!compat_pskb_may_pull(skb, ctx->copy_size))) {
-         goto err;
+      if (!adapter->is_shm) {
+         /* make sure headers are accessible directly */
+         if (UNLIKELY(!compat_pskb_may_pull(skb, ctx->copy_size))) {
+            goto err;
+         }
       }
    }
 
@@ -890,10 +900,19 @@ vmxnet3_parse_and_copy_hdr(struct sk_buff *skb,
    }
 
    tdd = tq->data_ring.base + tq->tx_ring.next2fill;
-   VMXNET3_ASSERT(ctx->copy_size <= compat_skb_headlen(skb));
+   VMXNET3_ASSERT(ctx->copy_size <= vmxnet3_skb_headlen(adapter, skb));
 
-   memcpy(tdd->data, skb->data, ctx->copy_size);
-   VMXNET3_LOG("copy %u bytes to dataRing[%u]\n", ctx->copy_size, tq->tx_ring.next2fill);
+   if (!adapter->is_shm) {
+      memcpy(tdd->data, skb->data, ctx->copy_size);
+   } else {
+      void *virt = kmap(VMXNET3_SHM_IDX2PAGE(adapter->shm, VMXNET3_SHM_SKB_GETIDX(skb)));
+      memcpy(tdd->data,
+             virt,
+             ctx->copy_size);
+      kunmap(virt);
+   }
+   VMXNET3_LOG("copy %u bytes to dataRing[%u]\n",
+               ctx->copy_size, tq->tx_ring.next2fill);
    return 1;
 
 err:
@@ -961,7 +980,7 @@ vmxnet3_prepare_tso(struct sk_buff *skb,
  *----------------------------------------------------------------------------
  */
 
-static int
+int
 vmxnet3_tq_xmit(struct sk_buff *skb,
                 struct vmxnet3_tx_queue *tq,
                 struct vmxnet3_adapter *adapter,
@@ -974,7 +993,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb,
    Vmxnet3_GenericDesc *gdesc;
 
    /* conservatively estimate # of descriptors to use */
-   count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + skb_shinfo(skb)->nr_frags + 1;
+   count = VMXNET3_TXD_NEEDED(vmxnet3_skb_headlen(adapter, skb)) +
+           skb_shinfo(skb)->nr_frags + 1;
 
    ctx.ipv4 = (skb->protocol == __constant_ntohs(ETH_P_IP));
 
@@ -990,6 +1010,14 @@ vmxnet3_tq_xmit(struct sk_buff *skb,
       vmxnet3_prepare_tso(skb, &ctx);
    } else {
       if (UNLIKELY(count > VMXNET3_MAX_TXD_PER_PKT)) {
+         if (UNLIKELY(adapter->is_shm)) {
+            VMXNET3_ASSERT(count <= VMXNET3_MAX_TXD_PER_PKT_SHM);
+            if (count > VMXNET3_MAX_TXD_PER_PKT_SHM) {
+               tq->stats.drop_too_many_frags++;
+               goto drop_pkt;
+            }
+         }
+
          /* non-tso pkts must not use more than VMXNET3_MAX_TXD_PER_PKT entries */
          if (compat_skb_linearize(skb) != 0) {
             tq->stats.drop_too_many_frags++;
@@ -998,11 +1026,11 @@ vmxnet3_tq_xmit(struct sk_buff *skb,
          tq->stats.linearized++;
 
          /* recalculate the # of descriptors to use */
-         count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+         count = VMXNET3_TXD_NEEDED(vmxnet3_skb_headlen(adapter, skb)) + 1;
       }
    }
 
-   ret = vmxnet3_parse_and_copy_hdr(skb, tq, &ctx);
+   ret = vmxnet3_parse_and_copy_hdr(skb, tq, &ctx, adapter);
    if (ret >= 0) {
       VMXNET3_ASSERT(ret > 0 || ctx.copy_size == 0);
       /* hdrs parsed, check against other limits */
@@ -1036,7 +1064,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb,
    }
 
    /* fill tx descs related to addr & len */
-   vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev);
+   vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev, adapter);
 
    /* setup the EOP desc */
    ctx.eop_txd->dword[3] = VMXNET3_TXD_CQ | VMXNET3_TXD_EOP;
@@ -1087,7 +1115,7 @@ hdr_too_big:
    tq->stats.drop_oversized_hdr++;
 drop_pkt:
    tq->stats.drop_total++;
-   compat_dev_kfree_skb(skb, FREE_WRITE);
+   vmxnet3_dev_kfree_skb(adapter, skb);
    return COMPAT_NETDEV_TX_OK;
 }
 
@@ -1113,6 +1141,11 @@ static int
 vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
    struct vmxnet3_adapter *adapter = compat_netdev_priv(netdev);
+
+   if (adapter->is_shm) {
+      return vmxnet3_shm_start_tx(skb, netdev);
+   }
+
    struct vmxnet3_tx_queue *tq = &adapter->tx_queue;
 
    return vmxnet3_tq_xmit(skb, tq, adapter, netdev);
@@ -1178,7 +1211,8 @@ vmxnet3_unmap_tx_buf(struct vmxnet3_tx_buf_info *tbi,
 static int
 vmxnet3_unmap_pkt(uint32 eop_idx,
                   struct vmxnet3_tx_queue *tq,
-                  struct pci_dev *pdev)
+                  struct pci_dev *pdev,
+                  struct vmxnet3_adapter *adapter)
 {
    struct sk_buff *skb;
    int entries = 0;
@@ -1206,7 +1240,7 @@ vmxnet3_unmap_pkt(uint32 eop_idx,
       entries ++;
    }
 
-   compat_dev_kfree_skb_any(skb, FREE_WRITE);
+   vmxnet3_dev_kfree_skb_any(adapter, skb);
    return entries;
 }
 
@@ -1233,7 +1267,8 @@ vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq,
 
    gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
    while (gdesc->tcd.gen == tq->comp_ring.gen) {
-      completed += vmxnet3_unmap_pkt(gdesc->tcd.txdIdx, tq, adapter->pdev);
+      completed += vmxnet3_unmap_pkt(gdesc->tcd.txdIdx, tq,
+                                     adapter->pdev, adapter);
 
       vmxnet3_comp_ring_adv_next2proc(&tq->comp_ring);
       gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
@@ -1279,7 +1314,7 @@ vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq,
 
       vmxnet3_unmap_tx_buf(tbi, adapter->pdev);
       if (tbi->skb) {
-         compat_dev_kfree_skb_any(tbi->skb, FREE_WRITE);
+         vmxnet3_dev_kfree_skb_any(adapter, tbi->skb);
          tbi->skb = NULL;
       }
       vmxnet3_cmd_ring_adv_next2comp(&tq->tx_ring);
@@ -1497,15 +1532,18 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq,
 
       if (rbi->buf_type == VMXNET3_RX_BUF_SKB) {
          if (rbi->skb == NULL) {
-            rbi->skb = dev_alloc_skb(rbi->len + COMPAT_NET_IP_ALIGN);
+            rbi->skb = vmxnet3_dev_alloc_skb(adapter, rbi->len + COMPAT_NET_IP_ALIGN);
             if (UNLIKELY(rbi->skb == NULL)) {
                rq->stats.rx_buf_alloc_failure++;
                break;
             }
-            skb_reserve(rbi->skb, COMPAT_NET_IP_ALIGN);
             rbi->skb->dev = adapter->netdev;
-            rbi->dma_addr = pci_map_single(adapter->pdev, rbi->skb->data,
-                                           rbi->len, PCI_DMA_FROMDEVICE);
+
+            if (!adapter->is_shm) {
+               skb_reserve(rbi->skb, COMPAT_NET_IP_ALIGN);
+            }
+            rbi->dma_addr = vmxnet3_map_single(adapter, rbi->skb, 0,
+                                               rbi->len, PCI_DMA_FROMDEVICE);
          } else {
             /* rx buffer skipped by the device */
          }
@@ -1515,13 +1553,14 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq,
                         rbi->len  == PAGE_SIZE);
 
          if (rbi->page == NULL) {
-            rbi->page = alloc_page(GFP_ATOMIC);
+            rbi->page = vmxnet3_alloc_page(adapter);
             if (UNLIKELY(rbi->page == NULL)) {
                rq->stats.rx_buf_alloc_failure++;
                break;
             }
-            rbi->dma_addr = pci_map_page(adapter->pdev, rbi->page, 0,
-                                         PAGE_SIZE, PCI_DMA_FROMDEVICE);
+            rbi->dma_addr = vmxnet3_map_page(adapter, rbi->page,
+                                             0, PAGE_SIZE,
+                                             PCI_DMA_FROMDEVICE);
          } else {
             /* rx buffers skipped by the device */
          }
@@ -1571,7 +1610,8 @@ vmxnet3_append_frag(struct sk_buff *skb,
                     Vmxnet3_RxCompDesc *rcd,
                     struct vmxnet3_rx_buf_info *rbi)
 {
-   struct skb_frag_struct *frag = skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
+   struct skb_frag_struct *frag = skb_shinfo(skb)->frags +
+                                  skb_shinfo(skb)->nr_frags;
 
    VMXNET3_ASSERT(skb_shinfo(skb)->nr_frags < MAX_SKB_FRAGS);
 
@@ -1646,7 +1686,8 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter,
 static void
 vmxnet3_rx_error(struct vmxnet3_rx_queue *rq,
                  Vmxnet3_RxCompDesc *rcd,
-                 struct vmxnet3_rx_ctx *ctx)
+                 struct vmxnet3_rx_ctx *ctx,
+                 struct vmxnet3_adapter *adapter)
 {
    rq->stats.drop_err++;
    if (!rcd->fcs) {
@@ -1654,7 +1695,7 @@ vmxnet3_rx_error(struct vmxnet3_rx_queue *rq,
    }
    rq->stats.drop_total++;
 
-   compat_dev_kfree_skb_irq(ctx->skb, FREE_WRITE);
+   vmxnet3_dev_kfree_skb_irq(adapter, ctx->skb);
    ctx->skb = NULL;
 }
 
@@ -1730,11 +1771,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
          ctx->skb = rbi->skb;
          rbi->skb = NULL;
 
-         skb_put(ctx->skb, rcd->len);
          pci_unmap_single(adapter->pdev,
                           rbi->dma_addr,
                           rbi->len,
                           PCI_DMA_FROMDEVICE);
+
+         vmxnet3_skb_put(adapter, ctx->skb, rcd->len);
       } else {
          VMXNET3_ASSERT(ctx->skb != NULL);
          /* non SOP buffer must be type 1 in most cases */
@@ -1742,11 +1784,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
             VMXNET3_ASSERT(rxd->btype == VMXNET3_RXD_BTYPE_BODY);
 
             if (rcd->len) {
-               vmxnet3_append_frag(ctx->skb, rcd, rbi);
                pci_unmap_page(adapter->pdev,
                               rbi->dma_addr,
                               rbi->len,
                               PCI_DMA_FROMDEVICE);
+
+               vmxnet3_append_frag(ctx->skb, rcd, rbi);
                rbi->page = NULL;
             }
          } else {
@@ -1767,30 +1810,37 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 
       skb = ctx->skb;
       if (rcd->eop) {
-         skb->len += skb->data_len;
-         skb->truesize += skb->data_len;
-
          if (UNLIKELY(rcd->err)) {
-            vmxnet3_rx_error(rq, rcd, ctx);
+            vmxnet3_rx_error(rq, rcd, ctx, adapter);
             goto rcd_done;
          }
 
-         vmxnet3_rx_csum(adapter, skb, (Vmxnet3_GenericDesc*)rcd);
-         skb->protocol = eth_type_trans(skb, adapter->netdev);
+         if (adapter->is_shm) {
+            vmxnet3_shm_rx_skb(adapter, skb);
 
-#ifdef VMXNET3_NAPI
-         if (UNLIKELY(adapter->vlan_grp && rcd->ts)) {
-            vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, rcd->tci);
+            wake_up(&adapter->shm->rxq);
          } else {
-            netif_receive_skb(skb);
-         }
+            skb->len += skb->data_len;
+            skb->truesize += skb->data_len;
+
+            vmxnet3_rx_csum(adapter, skb, (Vmxnet3_GenericDesc*)rcd);
+            skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+#ifdef VMXNET3_NAPI
+            if (UNLIKELY(adapter->vlan_grp && rcd->ts)) {
+               vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, rcd->tci);
+            } else {
+               netif_receive_skb(skb);
+            }
 #else
-         if (UNLIKELY(adapter->vlan_grp && rcd->ts)) {
-            vlan_hwaccel_rx(skb, adapter->vlan_grp, rcd->tci);
-         } else {
-            netif_rx(skb);
-         }
+            if (UNLIKELY(adapter->vlan_grp && rcd->ts)) {
+               vlan_hwaccel_rx(skb, adapter->vlan_grp, rcd->tci);
+            } else {
+               netif_rx(skb);
+            }
 #endif
+         }
+
          adapter->netdev->last_rx = jiffies;
          ctx->skb = NULL;
       }
@@ -1859,7 +1909,7 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq,
                              rxd->addr,
                              rxd->len,
                              PCI_DMA_FROMDEVICE);
-            compat_dev_kfree_skb(rq->buf_info[ring_idx][i].skb, FREE_WRITE);
+            vmxnet3_dev_kfree_skb(adapter, rq->buf_info[ring_idx][i].skb);
             rq->buf_info[ring_idx][i].skb = NULL;
          } else if (rxd->btype == VMXNET3_RXD_BTYPE_BODY &&
                     rq->buf_info[ring_idx][i].page) {
@@ -1867,7 +1917,7 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq,
                            rxd->addr,
                            rxd->len,
                            PCI_DMA_FROMDEVICE);
-            put_page(rq->buf_info[ring_idx][i].page);
+            vmxnet3_put_page(adapter, rq->buf_info[ring_idx][i].page);
             rq->buf_info[ring_idx][i].page = NULL;
          }
       }
@@ -2836,6 +2886,10 @@ vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter)
       adapter->rx_buf_per_pkt = 1 + (sz + PAGE_SIZE - 1) / PAGE_SIZE;
    }
 
+   if (adapter->is_shm) {
+      adapter->skb_buf_size = PAGE_SIZE;
+   }
+
    /*
     * for simplicity, force the ring0 size to be a multiple of
     * rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN
@@ -2927,6 +2981,14 @@ vmxnet3_open(struct net_device *netdev)
 
    spin_lock_init(&adapter->tx_queue.tx_lock);
 
+   if (adapter->is_shm) {
+      printk(KERN_INFO "bringing up shared memory vmxnet3 %s\n", netdev->name);
+      err = vmxnet3_shm_open(adapter, netdev->name);
+      if (err) {
+         goto shm_err;
+      }
+   }
+
    err = vmxnet3_create_queues(adapter, VMXNET3_DEF_TX_RING_SIZE, 
                                VMXNET3_DEF_RX_RING_SIZE, VMXNET3_DEF_RX_RING_SIZE);
    if (err) {
@@ -2946,6 +3008,8 @@ activate_err:
    vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
    vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
 queue_err:
+   vmxnet3_shm_close(adapter);
+shm_err:
    return err;
 }
 
@@ -2965,12 +3029,18 @@ vmxnet3_close(struct net_device *netdev)
 
    vmxnet3_quiesce_dev(adapter);
 
+   if (adapter->is_shm) {
+      vmxnet3_shm_close(adapter);
+   }
+
    vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
    vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
 
    COMPAT_NETDEV_MOD_DEC_USE_COUNT;
 
    clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+
+
    return 0;
 }
 
@@ -4156,6 +4226,24 @@ static int
 vmxnet3_probe_device(struct pci_dev *pdev,
                      const struct pci_device_id *id)
 {
+#ifdef HAVE_NET_DEVICE_OPS
+   static const struct net_device_ops vmxnet3_netdev_ops = {
+      .ndo_open  = vmxnet3_open,
+      .ndo_stop  = vmxnet3_close,
+      .ndo_start_xmit = vmxnet3_xmit_frame,
+      .ndo_set_mac_address = vmxnet3_set_mac_addr,
+      .ndo_change_mtu = vmxnet3_change_mtu,
+      .ndo_get_stats = vmxnet3_get_stats,
+      .ndo_tx_timeout = vmxnet3_tx_timeout,
+      .ndo_set_multicast_list = vmxnet3_set_mc,
+      .ndo_vlan_rx_register = vmxnet3_vlan_rx_register,
+      .ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
+      .ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
+#   ifdef CONFIG_NET_POLL_CONTROLLER
+      .ndo_poll_controller = vmxnet3_netpoll,
+#   endif
+   };
+#endif /* HAVE_NET_DEVICE_OPS */
    int err;
    Bool dma64 = FALSE; /* stupid gcc */
    uint32 ver;
@@ -4228,35 +4316,52 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 
    vmxnet3_declare_features(adapter, dma64);
 
+   adapter->dev_number = devices_found;
+   adapter->is_shm = FALSE;
+   if (adapter->dev_number < VMXNET3_SHM_MAX_DEVICES) {
+      if (enable_shm[adapter->dev_number] == 1) {
+         if (shm_disclaimer == NULL ||
+             strncmp(shm_disclaimer, VMXNET3_SHM_DISCLAIMER,
+                     strlen(VMXNET3_SHM_DISCLAIMER)) != 0) {
+            printk(KERN_ERR "Did not activate shm, disclaimer missing\n");
+         } else {
+            adapter->is_shm = TRUE;
+         }
+      }
+   }
+
    vmxnet3_alloc_intr_resources(adapter);
 
    vmxnet3_read_mac_addr(adapter, mac);
    memcpy(netdev->dev_addr,  mac, netdev->addr_len);
 
+#ifdef HAVE_NET_DEVICE_OPS
+   netdev->netdev_ops = &vmxnet3_netdev_ops;
+#else
    netdev->open  = vmxnet3_open;
    netdev->stop  = vmxnet3_close;
    netdev->hard_start_xmit = vmxnet3_xmit_frame;
    netdev->set_mac_address = vmxnet3_set_mac_addr;
    netdev->change_mtu = vmxnet3_change_mtu;
    netdev->get_stats = vmxnet3_get_stats;
-   SET_ETHTOOL_OPS(netdev, &vmxnet3_ethtool_ops);
    netdev->tx_timeout = vmxnet3_tx_timeout;
-   netdev->watchdog_timeo = 5 * HZ;
-
-   COMPAT_INIT_WORK(&adapter->work, vmxnet3_reset_work, adapter);
-
-#ifdef VMXNET3_NAPI
-   compat_netif_napi_add(netdev, &adapter->napi, vmxnet3_poll, 64);
-#endif
-
    netdev->set_multicast_list = vmxnet3_set_mc;
    netdev->vlan_rx_register = vmxnet3_vlan_rx_register;
    netdev->vlan_rx_add_vid  = vmxnet3_vlan_rx_add_vid;
    netdev->vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid;
-
 #ifdef CONFIG_NET_POLL_CONTROLLER
    netdev->poll_controller  = vmxnet3_netpoll;
 #endif
+#endif /* HAVE_NET_DEVICE_OPS */
+
+   netdev->watchdog_timeo = 5 * HZ;
+   SET_ETHTOOL_OPS(netdev, &vmxnet3_ethtool_ops);
+
+   COMPAT_INIT_WORK(&adapter->work, vmxnet3_reset_work, adapter);
+
+#ifdef VMXNET3_NAPI
+   compat_netif_napi_add(netdev, &adapter->napi, vmxnet3_poll, 64);
+#endif
 
    COMPAT_SET_MODULE_OWNER(netdev);
    COMPAT_SET_NETDEV_DEV(netdev, &pdev->dev);
@@ -4268,6 +4373,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
    }
 
    set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
+   devices_found++;
    return 0;
 
 err_register:
@@ -4364,6 +4470,7 @@ vmxnet3_suspend(struct pci_dev *pdev, pm_message_t state)
       return 0;
    }
 
+   vmxnet3_disable_all_intrs(adapter);
    netif_device_detach(netdev);
    netif_stop_queue(netdev);
 
@@ -4494,6 +4601,7 @@ vmxnet3_resume(struct pci_dev *pdev)
    pci_enable_wake(pdev, PCI_D0, 0);
 
    VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_PMCFG);
+   vmxnet3_enable_all_intrs(adapter);
 
    return 0;
 }
@@ -4564,4 +4672,13 @@ MODULE_VERSION(VMXNET3_DRIVER_VERSION_STRING);
  */
 MODULE_INFO(supported, "external");
 module_param(disable_lro, int, 0);
-
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 2)
+MODULE_PARM(enable_shm, "0-10i");
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
+module_param_array(enable_shm, int, num_enable_shm, 0);
+#else
+module_param_array(enable_shm, int, &num_enable_shm, 0);
+#endif
+MODULE_PARM_DESC(enable_shm, "Shared memory enable");
+module_param(shm_disclaimer, charp, 0);
+MODULE_PARM_DESC(shm_disclaimer, "Shared memory disclaimer");
index bbc9d3216c020a6aa5874a3a13f7b8fd9a8c1617..c0c544fde4bb4ff0eccf7f9e7dc6046017f677cc 100644 (file)
 
 #include "vmxnet3_defs.h"
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && !defined(VMXNET3_NO_NAPI)
+#   define VMXNET3_NAPI
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+#   define VMXNET3_NEW_NAPI
+#endif
+#endif
+
 typedef struct vmxnet3_cmd_ring {
    Vmxnet3_GenericDesc *base;
    uint32               size;
@@ -146,6 +153,7 @@ struct vmxnet3_rx_buf_info {
    union {
       struct sk_buff *skb;
       struct page    *page;
+      unsigned long   shm_idx;
    };
    dma_addr_t dma_addr;
 };
@@ -231,6 +239,10 @@ struct vmxnet3_adapter {
    compat_work work;
 
    unsigned long  state;    /* VMXNET3_STATE_BIT_xxx */
+
+   int dev_number;
+   Bool is_shm;
+   struct vmxnet3_shm_pool *shm;
 };
 
 struct vmxnet3_stat_desc {
@@ -264,3 +276,23 @@ struct vmxnet3_stat_desc {
 
 #define VMXNET3_MAX_SKB_BUF_SIZE    (3*1024)
 #endif
+
+#ifdef VMX86_DEBUG
+#   define VMXNET3_ASSERT(cond) BUG_ON(!(cond))
+#else
+#   define VMXNET3_ASSERT(cond) do {} while (0)
+#endif
+
+#ifdef VMXNET3_DO_LOG
+#   define VMXNET3_LOG(msg...) printk(KERN_ERR msg)
+#else
+#   define VMXNET3_LOG(msg...)
+#endif
+
+// used by vmxnet3_shm_tx_pkt
+int
+vmxnet3_tq_xmit(struct sk_buff *skb,
+                struct vmxnet3_tx_queue *tq,
+                struct vmxnet3_adapter *adapter,
+                struct net_device *netdev);
+
diff --git a/open-vm-tools/modules/linux/vmxnet3/vmxnet3_shm.c b/open-vm-tools/modules/linux/vmxnet3/vmxnet3_shm.c
new file mode 100644 (file)
index 0000000..eee0cf3
--- /dev/null
@@ -0,0 +1,1419 @@
+/*********************************************************
+ * Copyright (C) 2009 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
+ *
+ *********************************************************/
+
+/*
+ * vmxnet3_shm.c --
+ *
+ *    Shared memory infrastructure for VMXNET3 linux driver. Used by the
+ *    VMXNET3 driver to back its rings with memory from a shared memory
+ *    pool that is shared with user space.
+ */
+#include "driver-config.h"
+
+#include "compat_module.h"
+#include <linux/moduleparam.h>
+
+#include "compat_slab.h"
+#include "compat_spinlock.h"
+#include "compat_ioport.h"
+#include "compat_pci.h"
+#include "compat_highmem.h"
+#include "compat_init.h"
+#include "compat_timer.h"
+#include "compat_netdevice.h"
+#include "compat_skbuff.h"
+#include "compat_interrupt.h"
+#include "compat_workqueue.h"
+
+#include <asm/dma.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/in.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <asm/checksum.h>
+
+#include <linux/if_vlan.h>
+#include <linux/if_arp.h>
+#include <linux/inetdevice.h>
+
+#include "vm_basic_types.h"
+#include "vmnet_def.h"
+#include "vm_device_version.h"
+#include "vmxnet3_version.h"
+
+
+#include "vmxnet3_int.h"
+#include "vmxnet3_shm.h"
+
+
+static int
+vmxnet3_shm_consume_user_tx_queue(struct vmxnet3_shm_pool *shm);
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * kernel_rx_idx --
+ *
+ * Result:
+ *    Kernel's current shared memory RX ring index
+ *
+ * Side-effects:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static inline uint16
+kernel_rx_idx(const struct vmxnet3_shm_pool *shm)
+{
+   return shm->ctl.ptr->kernel_rxi;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * inc_kernel_rx_idx --
+ *
+ * Result:
+ *    None
+ *
+ * Side-effects:
+ *    Increment the kernel's shared memory RX ring index
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static inline void
+inc_kernel_rx_idx(const struct vmxnet3_shm_pool *shm)
+{
+   shm->ctl.ptr->kernel_rxi = (shm->ctl.ptr->kernel_rxi + 1) % SHM_RX_RING_SIZE;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * kernel_rx_idx --
+ *
+ * Result:
+ *    Kernel's current shared memory RX ring index
+ *
+ * Side-effects:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static inline uint16
+kernel_tx_idx(const struct vmxnet3_shm_pool *shm)
+{
+   return shm->ctl.ptr->kernel_txi;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * inc_kernel_tx_idx --
+ *
+ * Result:
+ *    None
+ *
+ * Side-effects:
+ *    Increment the kernel's shared memory TX ring index
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static inline void
+inc_kernel_tx_idx(const struct vmxnet3_shm_pool *shm)
+{
+   shm->ctl.ptr->kernel_txi = (shm->ctl.ptr->kernel_txi + 1) % SHM_TX_RING_SIZE;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * user_rx_idx --
+ *
+ * Result:
+ *    Users's current shared memory RX ring index
+ *
+ * Side-effects:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static inline uint16
+user_rx_idx(const struct vmxnet3_shm_pool *shm)
+{
+   return shm->ctl.ptr->user_rxi;
+}
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * kernel_rx_entry --
+ *
+ * Result:
+ *    Kernel's current shared memory RX ring entry
+ *
+ * Side-effects:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static inline struct vmxnet3_shm_ringentry *
+kernel_rx_entry(const struct vmxnet3_shm_pool *shm)
+{
+   return &shm->ctl.ptr->rx_ring[kernel_rx_idx(shm)];
+}
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * kernel_tx_entry --
+ *
+ * Result:
+ *    Kernel's current shared memory TX ring entry
+ *
+ * Side-effects:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static inline struct vmxnet3_shm_ringentry *
+kernel_tx_entry(const struct vmxnet3_shm_pool *shm)
+{
+   return &shm->ctl.ptr->tx_ring[kernel_tx_idx(shm)];
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * user_rx_entry --
+ *
+ * Used by vmxnet3_shm_chardev_poll
+ *
+ * Result:
+ *    User's current shared memory RX ring entry
+ *
+ * Side-effects:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static inline struct vmxnet3_shm_ringentry *
+user_rx_entry(const struct vmxnet3_shm_pool *shm)
+{
+   return &shm->ctl.ptr->rx_ring[user_rx_idx(shm)];
+}
+
+
+// kobject type
+static void
+vmxnet3_shm_pool_release(struct kobject *kobj);
+
+static const struct kobj_type vmxnet3_shm_pool_type = {
+   .release = vmxnet3_shm_pool_release
+};
+
+// vm operations
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static int
+vmxnet3_shm_chardev_fault(struct vm_area_struct *vma,
+                          struct vm_fault *vmf);
+
+static struct vm_operations_struct vmxnet3_shm_vm_ops = {
+   .fault = vmxnet3_shm_chardev_fault,
+};
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 1)
+static struct page *
+vmxnet3_shm_chardev_nopage(struct vm_area_struct *vma,
+                           unsigned long address,
+                           int *type);
+
+static struct vm_operations_struct vmxnet3_shm_vm_ops = {
+   .nopage = vmxnet3_shm_chardev_nopage,
+};
+#else
+static struct page *
+vmxnet3_shm_chardev_nopage(struct vm_area_struct *vma,
+                           unsigned long address,
+                           int unused);
+
+static struct vm_operations_struct vmxnet3_shm_vm_ops = {
+   .nopage = vmxnet3_shm_chardev_nopage,
+};
+#endif
+
+// file operations
+static int vmxnet3_shm_chardev_mmap(struct file *filp,
+                                    struct vm_area_struct *vma);
+
+static int vmxnet3_shm_chardev_open(struct inode * inode,
+                                    struct file * filp);
+
+static int vmxnet3_shm_chardev_release(struct inode * inode,
+                                       struct file * filp);
+
+static unsigned int vmxnet3_shm_chardev_poll(struct file *filp,
+                                             poll_table *wait);
+
+static int vmxnet3_shm_chardev_ioctl(struct inode *inode,
+                                     struct file *filp,
+                                     unsigned int cmd,
+                                     unsigned long arg);
+
+static struct file_operations shm_fops = {
+   .owner = THIS_MODULE,
+   .mmap = vmxnet3_shm_chardev_mmap,
+   .open = vmxnet3_shm_chardev_open,
+   .release = vmxnet3_shm_chardev_release,
+   .poll = vmxnet3_shm_chardev_poll,
+   .ioctl = vmxnet3_shm_chardev_ioctl,
+};
+
+static LIST_HEAD(vmxnet3_shm_list);
+static spinlock_t vmxnet3_shm_list_lock = SPIN_LOCK_UNLOCKED;
+
+////////////////////////////////// vmxnet3_shm_pool kobject
+
+
+//// Lifecycle
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+#define compat_kobject_init(kobj, ktype) { kobject_init(kobj, (struct kobj_type *) ktype); }
+#else
+#define compat_kobject_init(kobj, _ktype) {  \
+   (kobj)->ktype = (struct kobj_type *) _ktype; \
+   kobject_init(kobj); \
+   }
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_pool_create --
+ *
+ *    Allocate and initialize shared memory pool. Allocates the data and
+ *    control pages, resets them to zero, initializes locks, registers the
+ *    character device, etc. Creates virtual address mappings for the pool,
+ *    but does not set up DMA yet.
+ *
+ * Results:
+ *    The new shared memory pool object, or NULL on failure.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+struct vmxnet3_shm_pool *
+vmxnet3_shm_pool_create(struct vmxnet3_adapter *adapter,
+                        char *name)
+{
+   int i;
+   unsigned long flags;
+   struct vmxnet3_shm_pool *shm;
+   struct vmxnet3_shm_ctl *ctl_ptr;
+   struct page *ctl_page;
+
+   // Allocate shm_pool kobject
+   shm = kmalloc(sizeof(*shm), GFP_KERNEL);
+   if (shm == NULL) {
+      goto fail_shm;
+   }
+   memset(shm, 0, sizeof(*shm));
+   compat_kobject_init(&shm->kobj, &vmxnet3_shm_pool_type);
+   //shm->kobj.ktype = &vmxnet3_shm_pool_type;
+   //kobject_init(&shm->kobj);
+   snprintf(shm->name, sizeof(shm->name), "vmxnet_%s_shm", name);
+   kobject_set_name(&shm->kobj, shm->name);
+   shm->adapter = adapter;
+
+   // Allocate data pages
+   shm->data.num_pages = SHM_DATA_SIZE;
+   for (i = 1; i < shm->data.num_pages; i++) {
+#ifdef __GFP_ZERO
+      struct page *page = alloc_page(GFP_KERNEL|__GFP_ZERO);
+#else
+      struct page *page = alloc_page(GFP_KERNEL);
+#endif
+      if (page == NULL) {
+         goto fail_data;
+      }
+
+#ifndef __GFP_ZERO
+      {
+         void *virt = kmap(page);
+         memset(virt, 0, PAGE_SIZE);
+         kunmap(virt);
+      }
+#endif
+
+      VMXNET3_SHM_SET_IDX2PAGE(shm, i, page);
+      shm->allocator.stack[shm->allocator.count++] = i;
+
+      VMXNET3_ASSERT(i != SHM_INVALID_IDX);
+   }
+   VMXNET3_ASSERT(shm->allocator.count <= SHM_DATA_SIZE);
+
+   // Allocate control page
+   ctl_page = alloc_page(GFP_KERNEL);
+   if (ctl_page == NULL) {
+      goto fail_ctl;
+   }
+   ctl_ptr = (void*)kmap(ctl_page);
+   memset(ctl_ptr, 0, PAGE_SIZE);
+   shm->ctl.pages[0] = ctl_page;
+   shm->ctl.ptr = ctl_ptr;
+
+   // Register char device
+   shm->misc_dev.minor = MISC_DYNAMIC_MINOR;
+   shm->misc_dev.name = shm->name;
+   shm->misc_dev.fops = &shm_fops;
+   if (misc_register(&shm->misc_dev)) {
+      printk(KERN_ERR "failed to register vmxnet3_shm character device\n");
+      goto fail_cdev;
+   }
+
+   // Initialize locks
+   spin_lock_init(&shm->alloc_lock);
+   spin_lock_init(&shm->tx_lock);
+   spin_lock_init(&shm->rx_lock);
+   init_waitqueue_head(&shm->rxq);
+
+   spin_lock_irqsave(&vmxnet3_shm_list_lock, flags);
+   list_add(&shm->list, &vmxnet3_shm_list);
+   spin_unlock_irqrestore(&vmxnet3_shm_list_lock, flags);
+
+   printk(KERN_INFO "created vmxnet shared memory pool %s\n", shm->name);
+
+   return shm;
+
+fail_cdev:
+   kunmap(ctl_page);
+   __free_page(ctl_page);
+
+fail_data:
+fail_ctl:
+   for (i = 0; i < shm->data.num_pages; i++) {
+      if (VMXNET3_SHM_IDX2PAGE(shm, i) != NULL) {
+         __free_page(VMXNET3_SHM_IDX2PAGE(shm, i));
+      }
+   }
+
+   kfree(shm);
+
+fail_shm:
+   return NULL;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_pool_release --
+ *
+ *    Release a shared memory pool.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+vmxnet3_shm_pool_release(struct kobject *kobj)
+{
+   int i;
+   unsigned long flags;
+   struct vmxnet3_shm_pool *shm = container_of(kobj, struct vmxnet3_shm_pool, kobj);
+
+   spin_lock_irqsave(&vmxnet3_shm_list_lock, flags);
+   list_del(&shm->list);
+   spin_unlock_irqrestore(&vmxnet3_shm_list_lock, flags);
+
+   misc_deregister(&shm->misc_dev);
+
+   // Free control pages
+   for (i = 0; i < SHM_CTL_SIZE; i++) {
+      kunmap(shm->ctl.pages[i]);
+      __free_page(shm->ctl.pages[i]);
+   }
+
+   // Free data pages
+   for (i = 1; i < SHM_DATA_SIZE; i++) {
+      kunmap(VMXNET3_SHM_IDX2PAGE(shm,i));
+      __free_page(VMXNET3_SHM_IDX2PAGE(shm, i));
+   }
+
+   kfree(shm);
+
+   printk(KERN_INFO "destroyed vmxnet shared memory pool %s\n", shm->name);
+}
+
+
+//// Shared memory pool management
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_alloc_page --
+ *
+ *    Allocate a page from the shared memory area.
+ *
+ * Results:
+ *    Index to page or SHM_INVALID_IDX on failure.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+uint16
+vmxnet3_shm_alloc_page(struct vmxnet3_shm_pool *shm)
+{
+   uint16 idx;
+   unsigned long flags;
+
+   spin_lock_irqsave(&shm->alloc_lock, flags);
+   if (shm->allocator.count == 0) {
+      idx = SHM_INVALID_IDX;
+   } else {
+      idx = shm->allocator.stack[--shm->allocator.count];
+      VMXNET3_ASSERT(idx != SHM_INVALID_IDX);
+   }
+   //printk(KERN_INFO "allocator count: %d (alloc idx: %d)\n", shm->allocator.count, idx);
+   spin_unlock_irqrestore(&shm->alloc_lock, flags);
+
+   return idx;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_free_page --
+ *
+ *    Free a page back to the shared memory area
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+vmxnet3_shm_free_page(struct vmxnet3_shm_pool *shm,
+                      uint16 idx)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(&shm->alloc_lock, flags);
+   VMXNET3_ASSERT(shm->allocator.count < SHM_DATA_SIZE);
+   shm->allocator.stack[shm->allocator.count++] = idx;
+   //printk(KERN_INFO "allocator count: %d (freed idx: %d)\n", shm->allocator.count, idx);
+   spin_unlock_irqrestore(&shm->alloc_lock, flags);
+}
+
+
+//// Char device
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_addr2idx --
+ *
+ *    Convert user space address into index into the shared memory pool.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static inline unsigned long
+vmxnet3_shm_addr2idx(struct vm_area_struct *vma,
+                     unsigned long address)
+{
+   return vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT);
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_chardev_fault --
+ *
+ *    mmap fault handler. Called if the user space requests a page for
+ *    which there is no shared memory mapping yet. We need to lookup
+ *    the page we want to back the shared memory mapping with.
+ *
+ * Results:
+ *    The page backing the user space address.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+vmxnet3_shm_chardev_fault(struct vm_area_struct *vma,
+                          struct vm_fault *vmf)
+{
+   struct vmxnet3_shm_pool *shm = vma->vm_private_data;
+   unsigned long address = (unsigned long)vmf->virtual_address;
+   unsigned long idx = vmxnet3_shm_addr2idx(vma, address);
+   struct page *pageptr;
+
+   if (idx >= SHM_DATA_START && idx < SHM_DATA_START + SHM_DATA_SIZE) {
+      pageptr = VMXNET3_SHM_IDX2PAGE(shm, idx - SHM_DATA_START);
+   } else if (idx >= SHM_CTL_START && idx < SHM_CTL_START + SHM_CTL_SIZE) {
+      pageptr = shm->ctl.pages[idx - SHM_CTL_START];
+   } else {
+      pageptr = NULL;
+   }
+
+   if (pageptr) {
+      get_page(pageptr);
+   }
+
+   vmf->page = pageptr;
+
+   return pageptr ? VM_FAULT_MINOR : VM_FAULT_ERROR;
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 1)
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_chardev_nopage --
+ *
+ *    mmap nopage handler. Called if the user space requests a page for
+ *    which there is no shared memory mapping yet. We need to lookup
+ *    the page we want to back the shared memory mapping with.
+ *
+ * Results:
+ *    The page backing the user space address.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static struct page *
+vmxnet3_shm_chardev_nopage(struct vm_area_struct *vma,
+                           unsigned long address,
+                           int *type)
+{
+   struct vmxnet3_shm_pool *shm = vma->vm_private_data;
+   unsigned long idx = vmxnet3_shm_addr2idx(vma, address);
+   struct page *pageptr;
+
+   if (idx >= SHM_DATA_START && idx < SHM_DATA_START + SHM_DATA_SIZE) {
+      pageptr = VMXNET3_SHM_IDX2PAGE(shm, idx - SHM_DATA_START);
+   } else if (idx >= SHM_CTL_START && idx < SHM_CTL_START + SHM_CTL_SIZE) {
+      pageptr = shm->ctl.pages[idx - SHM_CTL_START];
+   } else {
+      pageptr = NULL;
+   }
+
+   if (pageptr) {
+      get_page(pageptr);
+   }
+
+   if (type) {
+      *type = pageptr ? VM_FAULT_MINOR : VM_FAULT_SIGBUS;
+   }
+
+   return pageptr;
+}
+
+#else
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_chardev_nopage --
+ *
+ *    mmap nopage handler. Called if the user space requests a page for
+ *    which there is no shared memory mapping yet. We need to lookup
+ *    the page we want to back the shared memory mapping with.
+ *
+ * Results:
+ *    The page backing the user space address.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static struct page *
+vmxnet3_shm_chardev_nopage(struct vm_area_struct *vma,
+                           unsigned long address,
+                           int unused)
+{
+   struct vmxnet3_shm_pool *shm = vma->vm_private_data;
+   unsigned long idx = vmxnet3_shm_addr2idx(vma, address);
+   struct page *pageptr;
+
+   if (idx >= SHM_DATA_START && idx < SHM_DATA_START + SHM_DATA_SIZE) {
+      pageptr = VMXNET3_SHM_IDX2PAGE(shm, idx - SHM_DATA_START);
+   } else if (idx >= SHM_CTL_START && idx < SHM_CTL_START + SHM_CTL_SIZE) {
+      pageptr = shm->ctl.pages[idx - SHM_CTL_START];
+   } else {
+      pageptr = NULL;
+   }
+
+   if (pageptr) {
+      get_page(pageptr);
+   }
+
+   return pageptr;
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_chardev_mmap --
+ *
+ *    Setup mmap.
+ *
+ * Results:
+ *    Always 0.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static int
+vmxnet3_shm_chardev_mmap(struct file *filp,
+                         struct vm_area_struct *vma)
+{
+   vma->vm_private_data = filp->private_data;
+   vma->vm_ops = &vmxnet3_shm_vm_ops;
+   vma->vm_flags |= VM_RESERVED;
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_chardev_poll --
+ *
+ *    Poll called from user space. We consume the TX queue and then go to
+ *    sleep until we get woken up by an interrupt.
+ *
+ * Results:
+ *    Poll mask.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static unsigned int
+vmxnet3_shm_chardev_poll(struct file *filp,
+                         poll_table *wait)
+{
+   struct vmxnet3_shm_pool *shm = filp->private_data;
+   unsigned int mask = 0;
+   unsigned long flags;
+   struct vmxnet3_shm_ringentry *re;
+
+   // consume TX queue
+   vmxnet3_shm_consume_user_tx_queue(shm);
+
+   // Wait on the rxq for an interrupt to wake us
+   poll_wait(filp, &shm->rxq, wait);
+
+   // Check if the user's current RX entry is full
+   spin_lock_irqsave(&shm->rx_lock, flags);
+   re = user_rx_entry(shm);
+   if (re->own) {
+      // XXX: We need a comment that explains what this does.
+      mask |= POLLIN | POLLRDNORM;
+   }
+   spin_unlock_irqrestore(&shm->rx_lock, flags);
+
+   return mask;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_chardev_ioctl --
+ *
+ *    Handle ioctls from user space.
+ *
+ * Results:
+ *    Return code depends on ioctl.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+vmxnet3_shm_chardev_ioctl(struct inode *inode,
+                          struct file *filp,
+                          unsigned int cmd,
+                          unsigned long arg)
+{
+   struct vmxnet3_shm_pool *shm = filp->private_data;
+   uint16 idx;
+   uint16 idx1;
+   int i;
+
+   switch(cmd) {
+
+      case SHM_IOCTL_TX:
+         vmxnet3_shm_consume_user_tx_queue(shm);
+         return 0;
+
+      case SHM_IOCTL_ALLOC_ONE:
+         idx = vmxnet3_shm_alloc_page(shm);
+         if (idx != SHM_INVALID_IDX) {
+            return idx;
+         } else {
+            return -ENOMEM;
+         }
+
+      case SHM_IOCTL_ALLOC_MANY:
+         for (i = 0; i < arg; i++) {
+            idx = vmxnet3_shm_alloc_page(shm);
+            if (idx != SHM_INVALID_IDX) {
+               if (vmxnet3_shm_user_rx(shm, idx, 0, 1, 1)) {
+                  vmxnet3_shm_free_page(shm, idx);
+                  return -ENOMEM;
+               }
+            } else {
+               return -ENOMEM;
+            }
+         }
+         return 0;
+
+      case SHM_IOCTL_ALLOC_ONE_AND_MANY:
+         idx1 = vmxnet3_shm_alloc_page(shm);
+         if (idx1 == SHM_INVALID_IDX) {
+            return -ENOMEM;
+         }
+         for (i = 0; i < arg - 1; i++) {
+            idx = vmxnet3_shm_alloc_page(shm);
+            if (idx != SHM_INVALID_IDX) {
+               if (vmxnet3_shm_user_rx(shm, idx, 0, 1, 1)) {
+                  vmxnet3_shm_free_page(shm, idx);
+                  vmxnet3_shm_free_page(shm, idx1);
+                  return -ENOMEM;
+               }
+            } else {
+               vmxnet3_shm_free_page(shm, idx1);
+               return -ENOMEM;
+            }
+         }
+         return idx1;
+
+      case SHM_IOCTL_FREE_ONE:
+         if (arg != SHM_INVALID_IDX && arg < SHM_DATA_SIZE) {
+            vmxnet3_shm_free_page(shm, arg);
+         }
+         return 0;
+   }
+
+   return -ENOTTY;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_chardev_find_by_minor --
+ *
+ *    Find the right shared memory pool based on the minor number of the
+ *    char device.
+ *
+ * Results:
+ *    Pointer to the shared memory pool, or NULL on error.
+ *
+ * Side effects:
+ *    Takes a reference on the kobj of the shm object.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static struct vmxnet3_shm_pool *
+vmxnet3_shm_chardev_find_by_minor(unsigned int minor)
+{
+   struct vmxnet3_shm_pool *shm, *tmp;
+   unsigned long flags;
+
+   spin_lock_irqsave(&vmxnet3_shm_list_lock, flags);
+
+   list_for_each_entry_safe(shm, tmp, &vmxnet3_shm_list, list) {
+      if (shm->misc_dev.minor == minor && kobject_get(&shm->kobj)) {
+         spin_unlock_irqrestore(&vmxnet3_shm_list_lock, flags);
+         return shm;
+      }
+   }
+
+   spin_unlock_irqrestore(&vmxnet3_shm_list_lock, flags);
+
+   return NULL;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_chardev_open --
+ *
+ *    Find the right shared memory pool based on the minor number of the
+ *    char device.
+ *
+ * Results:
+ *    0 on success or -ENODEV if no device exists with the given minor number
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+vmxnet3_shm_chardev_open(struct inode * inode,
+                         struct file * filp)
+{
+   // Stash pointer to shm in file so file ops can use it
+   filp->private_data = vmxnet3_shm_chardev_find_by_minor(iminor(inode));
+   if (filp->private_data == NULL) {
+      return -ENODEV;
+   }
+
+   // XXX: What does this do??
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+//   filp->f_mapping->backing_dev_info = &directly_mappable_cdev_bdi;
+#endif
+
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_chardev_release --
+ *
+ *    Closing the char device. Release the ref count on the shared memory
+ *    pool, perform cleanup.
+ *
+ * Results:
+ *    Always 0.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+vmxnet3_shm_chardev_release(struct inode * inode,
+                            struct file * filp)
+{
+   struct vmxnet3_shm_pool *shm = filp->private_data;
+   kobject_put(&shm->kobj);
+
+   // XXX: I guess we should reset the control pages here
+
+   return 0;
+}
+
+
+//// TX and RX
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_free_skbpages --
+ *
+ *    Free the shared memory pages (secretly) backing this skb.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+vmxnet3_free_skbpages(struct vmxnet3_adapter *adapter,
+                      struct sk_buff *skb)
+{
+   int i;
+
+   vmxnet3_shm_free_page(adapter->shm, VMXNET3_SHM_SKB_GETIDX(skb));
+   for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+      struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+      vmxnet3_shm_free_page(adapter->shm, (unsigned long)frag->page);
+   }
+
+   skb_shinfo(skb)->nr_frags = 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_start_tx --
+ *
+ *    The shared memory vmxnet version of the hard_start_xmit routine.
+ *    Just frees the given packet as we do not intend to transmit any
+ *    packet given to us by the TCP/IP stack.
+ *
+ * Results:
+ *    Always 0 for success.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+vmxnet3_shm_start_tx(struct sk_buff *skb,
+                     struct net_device *dev)
+{
+   compat_dev_kfree_skb_irq(skb, FREE_WRITE);
+   return COMPAT_NETDEV_TX_OK;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_tx_pkt --
+ *
+ *    Send a packet (collection of ring entries) using h/w tx routine.
+ *
+ * Results:
+ *    0 on success. Negative value to indicate error
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static inline int
+vmxnet3_shm_tx_pkt(struct vmxnet3_adapter *adapter,
+                   struct vmxnet3_shm_ringentry *res,
+                   int frags)
+{
+   struct sk_buff* skb;
+   int i;
+
+   skb = dev_alloc_skb(100);
+   if (skb == NULL) {
+      VMXNET3_ASSERT(FALSE);
+      return -ENOMEM;
+   }
+
+   VMXNET3_SHM_SKB_SETIDX(skb, res[0].idx);
+   VMXNET3_SHM_SKB_SETLEN(skb, res[0].len);
+
+   for (i = 1; i < frags; i++) {
+      struct skb_frag_struct *frag = skb_shinfo(skb)->frags +
+                                     skb_shinfo(skb)->nr_frags;
+
+      VMXNET3_ASSERT(skb_shinfo(skb)->nr_frags < MAX_SKB_FRAGS);
+
+      frag->page = (struct page*)(unsigned long)res[i].idx;
+      frag->page_offset = 0;
+      frag->size = res[i].len;
+      skb_shinfo(skb)->nr_frags ++;
+   }
+
+   {
+      struct vmxnet3_tx_queue *tq = &adapter->tx_queue;
+      int ret;
+      skb->protocol = cpu_to_be16(0x86dd);
+      adapter->shm->ctl.ptr->stats.kernel_tx += frags; // XXX: move to better place
+      ret = vmxnet3_tq_xmit(skb, tq, adapter, adapter->netdev);
+      if (ret == COMPAT_NETDEV_TX_BUSY) {
+         for (i = 0; i < frags; i++) {
+            vmxnet3_shm_free_page(adapter->shm, res[i].idx);
+         }
+         skb_shinfo(skb)->nr_frags = 0;
+         kfree_skb(skb);
+      }
+
+      return ret;
+   }
+
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_tx_re --
+ *
+ *    Add one entry to the partial TX array. If re->eop is set, i.e. if
+ *    the packet is complete, TX the partial packet.
+ *
+ * Results:
+ *    1 if eop
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+vmxnet3_shm_tx_re(struct vmxnet3_shm_pool *shm,
+                  struct vmxnet3_shm_ringentry re)
+{
+   int i;
+
+   shm->partial_tx.res[shm->partial_tx.frags++] = re;
+
+   if (re.eop) {
+      int status = vmxnet3_shm_tx_pkt(shm->adapter,
+                                     shm->partial_tx.res,
+                                     shm->partial_tx.frags);
+      if (status < 0) {
+         for (i = 0; i < shm->partial_tx.frags; i++) {
+            vmxnet3_shm_free_page(shm, shm->partial_tx.res[i].idx);
+         }
+      }
+      shm->partial_tx.frags = 0;
+      return 1;
+   }
+
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_consume_user_tx_queue --
+ *
+ *    Consume all packets in the user TX queue and send full
+ *    packets to the device
+ *
+ * Results:
+ *    0 on success.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+vmxnet3_shm_consume_user_tx_queue(struct vmxnet3_shm_pool *shm)
+{
+   unsigned long flags;
+   struct vmxnet3_shm_ringentry *re;
+
+   spin_lock_irqsave(&shm->tx_lock, flags);
+
+   // Check if the device has been closed
+   if (shm->adapter == NULL) {
+      spin_unlock_irqrestore(&shm->tx_lock, flags);
+      return -1;
+   }
+
+   /*
+    * Loop through each full entry in the user TX ring. Discard trash frags and
+    * add the others to the partial TX array. If an entry has eop set, TX the
+    * partial packet.
+    */
+   while ((re = kernel_tx_entry(shm))->own) {
+      if (re->trash) {
+         vmxnet3_shm_free_page(shm, re->idx);
+         shm->ctl.ptr->stats.kernel_tx++;
+      } else {
+         vmxnet3_shm_tx_re(shm, *re);
+      }
+      inc_kernel_tx_idx(shm);
+      *re = RE_ZERO;
+   }
+
+   spin_unlock_irqrestore(&shm->tx_lock, flags);
+
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_user_desc_available --
+ *
+ *    Checks if we have num_entries ring entries available on the rx ring.
+ *
+ * Results:
+ *    0 for yes
+ *    -ENOMEM for not enough entries available
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+vmxnet3_shm_user_desc_available(struct vmxnet3_shm_pool *shm,
+                                uint16 num_entries)
+{
+   struct vmxnet3_shm_ringentry *re;
+   uint16 reIdx = kernel_rx_idx(shm);
+
+   while (num_entries > 0) {
+      re = &shm->ctl.ptr->rx_ring[reIdx];
+      if (re->own) {
+         return -ENOMEM;
+      }
+      reIdx = (reIdx + 1) % SHM_RX_RING_SIZE;
+      num_entries--;
+   }
+
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_rx_skb --
+ *
+ *    Receives an skb into the rx ring. If we can't receive all fragments,
+ *    the entire skb is dropped.
+ *
+ * Results:
+ *    0 for success
+ *    -ENOMEM for not enough entries available
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+vmxnet3_shm_rx_skb(struct vmxnet3_adapter *adapter,
+                   struct sk_buff *skb)
+{
+   int ret;
+   int i;
+   int num_entries = 1 + skb_shinfo(skb)->nr_frags;
+   int eop = (num_entries == 1);
+
+   if (vmxnet3_shm_user_desc_available(adapter->shm, num_entries) == -ENOMEM) {
+      vmxnet3_dev_kfree_skb_irq(adapter, skb);
+      return -ENOMEM;
+   }
+
+   ret = vmxnet3_shm_user_rx(adapter->shm,
+                            VMXNET3_SHM_SKB_GETIDX(skb),
+                            VMXNET3_SHM_SKB_GETLEN(skb),
+                            0 /* trash */,
+                            eop);
+   if (ret != 0) {
+      VMXNET3_ASSERT(FALSE);
+      printk(KERN_ERR "vmxnet3_shm_user_rx failed on frag 0\n");
+   }
+
+   for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+      struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+      unsigned long shm_idx = (unsigned long)frag->page;
+
+      eop = (i == skb_shinfo(skb)->nr_frags - 1);
+
+      ret = vmxnet3_shm_user_rx(adapter->shm,
+                               shm_idx,
+                               frag->size,
+                               0 /* trash */,
+                               eop);
+      if (ret != 0) {
+         VMXNET3_ASSERT(FALSE);
+         printk(KERN_ERR "vmxnet3_shm_user_rx failed on frag 1+\n");
+      }
+   }
+
+
+   /*
+    * Do NOT use the vmxnet3 version of kfree_skb, as we handed
+    * ownership of shm pages to the user space, thus we must not
+    * free them again.
+    */
+   skb_shinfo(skb)->nr_frags = 0;
+   compat_dev_kfree_skb_irq(skb, FREE_WRITE);
+
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_user_rx --
+ *
+ *    Put one packet fragment into the shared memory RX ring
+ *
+ * Results:
+ *    0 on success.
+ *    Negative value on error.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+vmxnet3_shm_user_rx(struct vmxnet3_shm_pool *shm,
+                    uint16 idx,
+                    uint16 len,
+                    int trash,
+                    int eop)
+{
+   struct vmxnet3_shm_ringentry *re = kernel_rx_entry(shm);
+   shm->ctl.ptr->stats.kernel_rx++;
+   if (re->own) {
+      return -ENOMEM;
+   }
+   inc_kernel_rx_idx(shm);
+   re->idx = idx;
+   re->len = len;
+   re->trash = trash;
+   re->eop = eop;
+   re->own = TRUE;
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_open --
+ *
+ *    Called when the vmxnet3 device is opened. Allocates the per-device
+ *    shared memory pool.
+ *
+ * Results:
+ *    0 on success.
+ *    Negative value on error.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+vmxnet3_shm_open(struct vmxnet3_adapter *adapter,
+                 char *name)
+{
+   adapter->shm = vmxnet3_shm_pool_create(adapter, name);
+   if (adapter->shm == NULL) {
+      printk(KERN_ERR "failed to create shared memory pool\n");
+      return -ENOMEM;
+   }
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_shm_close --
+ *
+ *    Called when the vmxnet3 device is closed. Does not free the per-device
+ *    shared memory pool. The character device might still be open. Thus
+ *    freeing the shared memory pool is tied to the ref count on
+ *    shm->kobj dropping to zero instead.
+ *
+ * Results:
+ *    0 on success.
+ *    Negative value on error.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+vmxnet3_shm_close(struct vmxnet3_adapter *adapter)
+{
+   unsigned long flags;
+
+   // Can't unset the lp pointer if a TX is in progress
+   spin_lock_irqsave(&adapter->shm->tx_lock, flags);
+   adapter->shm->adapter = NULL;
+   spin_unlock_irqrestore(&adapter->shm->tx_lock, flags);
+
+   kobject_put(&adapter->shm->kobj);
+   return 0;
+}
diff --git a/open-vm-tools/modules/linux/vmxnet3/vmxnet3_shm.h b/open-vm-tools/modules/linux/vmxnet3/vmxnet3_shm.h
new file mode 100644 (file)
index 0000000..a6cf90e
--- /dev/null
@@ -0,0 +1,317 @@
+/*********************************************************
+ * Copyright (C) 2009 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
+ *
+ *********************************************************/
+
+/*
+ * vmxnet3_shm.h --
+ *
+ *      Definitions for shared memory infrastructure for VMXNET3 linux driver.
+ */
+
+#ifndef _VMXNET3_SHM_H_
+#define _VMXNET3_SHM_H_
+
+#include "vmxnet3_shm_shared.h"
+#include <linux/miscdevice.h>
+
+/*
+ * Bumping up the max tx descriptor per packet.
+ * We need one more than VMXNET3_SHM_MAX_FRAGS because of partial header copy.
+ */
+#define VMXNET3_MAX_TXD_PER_PKT_SHM (VMXNET3_SHM_MAX_FRAGS + 1)
+
+struct vmxnet3_shm_mapped_page
+{
+   struct page *page;
+   void *virt;
+};
+
+struct vmxnet3_shm_pool
+{
+   struct list_head list;
+   char name[IFNAMSIZ + 16];
+   struct kobject kobj;
+
+   struct
+   {
+      // pages backing the map in virtual address order
+      struct vmxnet3_shm_mapped_page pages[SHM_DATA_SIZE];
+      unsigned int num_pages;
+   } data;
+
+   struct
+   {
+      // pages backing the map in virtual address order
+      struct page *pages[SHM_CTL_SIZE];
+      struct vmxnet3_shm_ctl *ptr;
+   } ctl;
+
+   struct
+   {
+      /*
+       * This is a stack of free pages. count is the number of free pages, so
+       * count - 1 is the topmost free page.
+       */
+      uint16 count;
+      uint16 stack[SHM_DATA_SIZE];
+   } allocator;
+
+   struct
+   {
+      struct vmxnet3_shm_ringentry res[VMXNET3_SHM_MAX_FRAGS];
+      int frags;
+   } partial_tx;
+
+   struct miscdevice misc_dev;
+
+   wait_queue_head_t rxq;
+   spinlock_t alloc_lock, tx_lock, rx_lock;
+   struct vmxnet3_adapter *adapter;
+};
+
+// Convert ring index to the struct page* or virt address.
+#define VMXNET3_SHM_IDX2PAGE(shm, idx) (shm->data.pages[(idx)].page)
+#define VMXNET3_SHM_SET_IDX2PAGE(shm, idx, x) (shm->data.pages[(idx)].page = (x))
+
+#define VMXNET3_SHM_SKB_GETIDX(skb) (compat_skb_transport_offset(skb))
+#define VMXNET3_SHM_SKB_SETIDX(skb, idx) (compat_skb_set_transport_header(skb, idx))
+#define VMXNET3_SHM_SKB_SETLEN(skb, len) (compat_skb_set_network_header(skb, len))
+#define VMXNET3_SHM_SKB_GETLEN(skb) (compat_skb_network_offset(skb))
+
+int
+vmxnet3_shm_close(struct vmxnet3_adapter *adapter);
+int
+vmxnet3_shm_open(struct vmxnet3_adapter *adapter, char *name);
+int
+vmxnet3_shm_user_rx(struct vmxnet3_shm_pool *shm,
+                   uint16 idx, uint16 len,
+                   int trash, int eop);
+void
+vmxnet3_free_skbpages(struct vmxnet3_adapter *adapter, struct sk_buff *skb);
+
+uint16
+vmxnet3_shm_alloc_page(struct vmxnet3_shm_pool *shm);
+void
+vmxnet3_shm_free_page(struct vmxnet3_shm_pool *shm, uint16 idx);
+
+int
+vmxnet3_shm_start_tx(struct sk_buff *skb, struct net_device *dev);
+int
+vmxnet3_shm_rx_skb(struct vmxnet3_adapter *adapter, struct sk_buff *skb);
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_dev_kfree_skb_* --
+ *
+ *      Covers for dev_kfree_skb*. Deal with the shared memory version of skbs.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static inline void
+vmxnet3_dev_kfree_skb(struct vmxnet3_adapter *adapter, struct sk_buff *skb)
+{
+   if (adapter->is_shm) {
+      vmxnet3_free_skbpages(adapter, skb);
+   }
+   compat_dev_kfree_skb(skb, FREE_WRITE);
+}
+
+static inline void
+vmxnet3_dev_kfree_skb_any(struct vmxnet3_adapter *adapter, struct sk_buff *skb)
+{
+   if (adapter->is_shm) {
+      vmxnet3_free_skbpages(adapter, skb);
+   }
+   compat_dev_kfree_skb_any(skb, FREE_WRITE);
+}
+
+static inline void
+vmxnet3_dev_kfree_skb_irq(struct vmxnet3_adapter *adapter, struct sk_buff *skb)
+{
+   if (adapter->is_shm) {
+      vmxnet3_free_skbpages(adapter, skb);
+   }
+   compat_dev_kfree_skb_irq(skb, FREE_WRITE);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_skb_* --
+ *
+ *      Covers for (compat_)skb_*. Deal with the shared memory version of skbs.
+ *
+ * Results:
+ *      Depends.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static inline unsigned int
+vmxnet3_skb_headlen(struct vmxnet3_adapter *adapter, struct sk_buff *skb)
+{
+   if (adapter->is_shm) {
+      return VMXNET3_SHM_SKB_GETLEN(skb);
+   } else {
+      return compat_skb_headlen(skb);
+   }
+}
+
+static inline void
+vmxnet3_skb_put(struct vmxnet3_adapter *adapter, struct sk_buff *skb, unsigned int len)
+{
+   if (!adapter->is_shm) {
+      skb_put(skb, len);
+   } else {
+      unsigned int oldlen = VMXNET3_SHM_SKB_GETLEN(skb);
+      VMXNET3_SHM_SKB_SETLEN(skb, len + oldlen);
+   }
+}
+
+static inline struct sk_buff*
+vmxnet3_dev_alloc_skb(struct vmxnet3_adapter *adapter, unsigned long length)
+{
+   if (adapter->is_shm) {
+      int idx;
+      struct sk_buff* skb;
+      idx = vmxnet3_shm_alloc_page(adapter->shm);
+      if (idx == SHM_INVALID_IDX) {
+         return NULL;
+      }
+
+      // The length is arbitrary because that memory shouldn't be used
+      skb = dev_alloc_skb(100);
+      if (skb == NULL) {
+         vmxnet3_shm_free_page(adapter->shm, idx);
+         return NULL;
+      }
+
+      VMXNET3_SHM_SKB_SETIDX(skb, idx);
+      VMXNET3_SHM_SKB_SETLEN(skb, 0);
+
+      return skb;
+   } else {
+      return dev_alloc_skb(length);
+   }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_map_* --
+ *
+ *      Covers for pci_map_*. Deal with the shared memory version of skbs.
+ *
+ * Results:
+ *      DMA address
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static inline dma_addr_t
+vmxnet3_map_single(struct vmxnet3_adapter *adapter,
+                   struct sk_buff * skb,
+                   size_t offset,
+                   size_t len,
+                   int direction)
+{
+   if (adapter->is_shm) {
+      unsigned long shm_idx = VMXNET3_SHM_SKB_GETIDX(skb);
+      struct page *real_page = VMXNET3_SHM_IDX2PAGE(adapter->shm, shm_idx);
+      return pci_map_page(adapter->pdev,
+                          real_page,
+                          offset,
+                          len,
+                          direction);
+   } else {
+      return pci_map_single(adapter->pdev,
+                            skb->data + offset,
+                            len,
+                            direction);
+   }
+
+}
+
+static inline dma_addr_t
+vmxnet3_map_page(struct vmxnet3_adapter *adapter,
+                 struct page *page,
+                 size_t offset,
+                 size_t len,
+                 int direction)
+{
+   if (adapter->is_shm) {
+      unsigned long shm_idx = (unsigned long)page;
+      page = VMXNET3_SHM_IDX2PAGE(adapter->shm, shm_idx);
+   }
+
+   return pci_map_page(adapter->pdev,
+                       page,
+                       offset,
+                       len,
+                       direction);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet3_(put|alloc)_page --
+ *
+ *      Allocation and release of pages. Either use regular or shared memory
+ *      pages.
+ *
+ * Results:
+ *      Depends
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static inline void
+vmxnet3_put_page(struct vmxnet3_adapter *adapter,
+                 struct page *page)
+{
+   if (!adapter->is_shm) {
+      put_page(page);
+   } else {
+      vmxnet3_shm_free_page(adapter->shm, (unsigned long)page);
+   }
+}
+
+static inline void *
+vmxnet3_alloc_page(struct vmxnet3_adapter *adapter)
+{
+   if (adapter->is_shm) {
+      return (void*) (unsigned long) vmxnet3_shm_alloc_page(adapter->shm);
+   } else {
+      return alloc_page(GFP_ATOMIC);
+   }
+}
+
+
+#endif
diff --git a/open-vm-tools/modules/linux/vmxnet3/vmxnet3_shm_shared.h b/open-vm-tools/modules/linux/vmxnet3/vmxnet3_shm_shared.h
new file mode 100644 (file)
index 0000000..e3eca68
--- /dev/null
@@ -0,0 +1,91 @@
+/*********************************************************
+ * Copyright (C) 2009 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
+ *
+ *********************************************************/
+
+/*
+ * vmxnet3_shm_shared.h --
+ *
+ *   Header shared between vmxnet3 shared memory kernel driver and userspace.
+ *
+ */
+
+#ifndef __VMXNET_SHARED_SHM
+#define __VMXNET_SHARED_SHM
+
+#include <linux/ioctl.h>
+
+// ioctl constants
+#define SHM_IOCTL_MAGIC 'v'
+#define SHM_IOCTL_TX                  _IO(SHM_IOCTL_MAGIC, 0)
+#define SHM_IOCTL_ALLOC_ONE           _IO(SHM_IOCTL_MAGIC, 1)
+#define SHM_IOCTL_ALLOC_MANY          _IO(SHM_IOCTL_MAGIC, 2)
+#define SHM_IOCTL_ALLOC_ONE_AND_MANY  _IO(SHM_IOCTL_MAGIC, 3)
+#define SHM_IOCTL_FREE_ONE            _IO(SHM_IOCTL_MAGIC, 4)
+
+/*
+ * invalid index
+ *
+ * Must be 0 so that a invalid shared memory page has the same
+ * value as a NULL struct page. We need that because we overload
+ * the same field for regular and shared memory version of vmxnet3.
+ */
+#define SHM_INVALID_IDX 0
+
+// sizes of shared memory regions in pages
+#define SHM_DATA_START 0
+#define SHM_DATA_SIZE 4096
+#define SHM_CTL_START 16384
+#define SHM_CTL_SIZE 1
+
+// ring size (in entries) is limited by the single control page - 4 bytes per re
+#define SHM_RX_RING_SIZE 507
+#define SHM_TX_RING_SIZE 507
+
+// maximum fragments per packet is 16 (64k) + 2 for metadata
+#define VMXNET3_SHM_MAX_FRAGS 18
+
+// shared memory ring entry
+struct vmxnet3_shm_ringentry
+{
+   uint16_t idx;      // index of this page in the pool
+   uint16_t len: 13;  // length of data in this page
+   uint16_t own: 1;   // whether the receiver owns the re
+   uint16_t eop: 1;   // end of packet
+   uint16_t trash: 1; // ignore all the data in this packet, but still take ownership
+};
+
+static const struct vmxnet3_shm_ringentry RE_ZERO = {0,0,0,0,0};
+
+// shared memory control page
+struct vmxnet3_shm_ctl
+{
+   struct vmxnet3_shm_ringentry rx_ring[SHM_RX_RING_SIZE];
+   struct vmxnet3_shm_ringentry tx_ring[SHM_TX_RING_SIZE];
+
+   // XXX move kernel_* into the kernel, currently here for debugging
+   // user_rxi is used by poll() to avoid going to sleep when there are packets waiting
+   uint16_t user_rxi, user_txi;
+   uint16_t kernel_rxi, kernel_txi;
+
+   struct
+   {
+      uint64_t user_rx, user_tx;
+      uint64_t kernel_rx, kernel_tx;
+   } stats;
+};
+
+#endif
index 80b817d464b75c1502a89a55e87641bc0940df6c..f3c0891c92249500e8d6b418c5fef3a299635c8c 100644 (file)
 #ifndef _VMXNET3_VERSION_H_
 #define _VMXNET3_VERSION_H_
 
-#define VMXNET3_DRIVER_VERSION          1.0.0.34
-#define VMXNET3_DRIVER_VERSION_COMMAS   1,0,0,34
-#define VMXNET3_DRIVER_VERSION_STRING   "1.0.0.34"
+#define VMXNET3_DRIVER_VERSION          1.0.1.0
+#define VMXNET3_DRIVER_VERSION_COMMAS   1,0,1,0
+#define VMXNET3_DRIVER_VERSION_STRING   "1.0.1.0"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01000022
+#define VMXNET3_DRIVER_VERSION_NUM      0x01000100
 
 #endif /* _VMXNET3_VERSION_H_ */
index ad97e838620e7d70b5e08238eb04113056caafeb..d152b5db065b4cb6ca17ceebda13c8b1d9518972 100644 (file)
@@ -871,7 +871,8 @@ VSockVmciRecvStreamCB(void *data,           // IN
     * Ignore incoming packets from contexts without sockets, or resources that
     * aren't vsock implementations.
     */
-   if (!VSockAddr_SocketContext(VMCI_HANDLE_TO_CONTEXT_ID(dg->src)) ||
+
+   if (!VSockAddr_SocketContextStream(VMCI_HANDLE_TO_CONTEXT_ID(dg->src)) ||
        VSOCK_PACKET_RID != VMCI_HANDLE_TO_RESOURCE_ID(dg->src)) {
       return VMCI_ERROR_NO_ACCESS;
    }
@@ -1491,10 +1492,10 @@ VSockVmciRecvListen(struct sock *sk,   // IN
    sk->compat_sk_ack_backlog++;
 
    pending->compat_sk_state = SS_CONNECTING;
-   vpending->produceSize = vpending->consumeSize = pkt->u.size;
+   vpending->produceSize = vpending->consumeSize = qpSize;
 
    /* XXX Move this into the notify file. */
-   vpending->notify.writeNotifyWindow = pkt->u.size;
+   vpending->notify.writeNotifyWindow = qpSize;
 
    /*
     * We might never receive another message for this socket and it's not
@@ -3106,6 +3107,12 @@ VSockVmciDgramConnect(struct socket *sock,   // IN
       }
    }
 
+   if (!VSockAddr_SocketContextDgram(remoteAddr->svm_cid,
+                                     remoteAddr->svm_port)) {
+      err = -EINVAL;
+      goto out;
+   }
+
    memcpy(&vsk->remoteAddr, remoteAddr, sizeof vsk->remoteAddr);
    sock->state = SS_CONNECTED;
 
@@ -3178,7 +3185,7 @@ VSockVmciStreamConnect(struct socket *sock,   // IN
       }
 
       /* The hypervisor and well-known contexts do not have socket endpoints. */
-      if (!VSockAddr_SocketContext(remoteAddr->svm_cid)) {
+      if (!VSockAddr_SocketContextStream(remoteAddr->svm_cid)) {
          err = -ENETUNREACH;
          goto out;
       }
@@ -3325,7 +3332,7 @@ VSockVmciAccept(struct socket *sock,     // IN
          err = sock_intr_errno(timeout);
          goto outWait;
       } else if (timeout == 0) {
-         err = -ETIMEDOUT;
+         err = -EAGAIN;
          goto outWait;
       }
 
@@ -3528,7 +3535,8 @@ VSockVmciPoll(struct file *file,    // IN
        * Sockets whose connections have been close, reset, or terminated should also
        * be considered read, and we check the shutdown flag for that.
        */
-      if (sk->compat_sk_shutdown) {
+      if (sk->compat_sk_shutdown & RCV_SHUTDOWN ||
+          vsk->peerShutdown & SEND_SHUTDOWN) {
           mask |= POLLIN | POLLRDNORM;
       }
 
@@ -3779,6 +3787,16 @@ VSockVmciDgramSendmsg(struct kiocb *kiocb,          // UNUSED
       goto out;
    }
 
+   /*
+    * Make sure that we don't allow a userlevel app to send datagrams
+    * to the hypervisor that modify VMCI device state.
+    */
+   if (!VSockAddr_SocketContextDgram(remoteAddr->svm_cid,
+                                     remoteAddr->svm_port)) {
+      err = -EINVAL;
+      goto out;
+   }
+
    /*
     * Allocate a buffer for the user's message and our packet header.
     */
index 8da3122fcd9a45081ab510624310291e88c7540a..cbdc00b649fc9d82fe3088e8a7c385d608ab4477 100644 (file)
@@ -351,10 +351,10 @@ exit:
 /*
  *----------------------------------------------------------------------------
  *
- * VSockAddr_SocketContext --
+ * VSockAddr_SocketContextStream --
  *
  *      Determines whether the provided context id represents a context that
- *      contains socket endpoints.
+ *      contains a stream socket endpoints.
  *
  * Results:
  *      TRUE if the context does have socket endpoints, FALSE otherwise.
@@ -366,7 +366,7 @@ exit:
  */
 
 Bool
-VSockAddr_SocketContext(uint32 cid)  // IN
+VSockAddr_SocketContextStream(uint32 cid)  // IN
 {
    uint32 i;
    VMCIId nonSocketContexts[] = {
@@ -384,3 +384,34 @@ VSockAddr_SocketContext(uint32 cid)  // IN
 
    return TRUE;
 }
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * VSockAddr_SocketContextDgram --
+ *
+ *      Determines whether the provided <context id, resource id> represent
+ *      a protected datagram endpoint.
+ *
+ * Results:
+ *      TRUE if the context does have socket endpoints, FALSE otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+VSockAddr_SocketContextDgram(uint32 cid,  // IN
+                             uint32 rid)  // IN
+{
+   if (cid == VMCI_HYPERVISOR_CONTEXT_ID) {
+      if (rid != VMCI_VSOCK_VMX_LOOKUP) {
+         return FALSE;
+      }
+   }
+
+   return TRUE;
+}
index e70f2b8c550a88dce1f788a7f7356b6711d16ef1..a90ea31f2b3a77cde7e78e3880fb3b51afbe6c3b 100644 (file)
@@ -45,8 +45,8 @@ Bool VSockAddr_EqualsHandlePort(struct sockaddr_vm *addr, VMCIHandle handle,
                                 uint32 port);
 int32 VSockAddr_Cast(const struct sockaddr *addr, int32 len,
                      struct sockaddr_vm **outAddr);
-Bool VSockAddr_SocketContext(VMCIId cid);
-
+Bool VSockAddr_SocketContextStream(uint32 cid);
+Bool VSockAddr_SocketContextDgram(uint32 cid, uint32 rid);
 
 #endif // _VSOCK_ADDR_H_
 
index 9f6b70e2dc9d30a9c9d8c89e27ca854d47006179..9a33653c44e9320686b7a5fed172cbc979092812 100644 (file)
@@ -69,7 +69,6 @@ typedef enum NetSG_AddrType {
    NET_SG_MACH_ADDR,
    NET_SG_PHYS_ADDR,
    NET_SG_VIRT_ADDR,
-   NET_SG_VMM_STACK_OFFSET,
 } NetSG_AddrType;
 
 typedef struct NetSG_Array {
index f086a3a913fb4d512ba1de20e7b4a0119605c7b3..a2c30e265a0364e1f206c90505205c72ab3d17ad 100644 (file)
@@ -5,5 +5,6 @@ Encoding=UTF-8
 # be sure to also fix up OVT staging targets.
 Exec=vmware-user-suid-wrapper
 Name=VMware User Agent
-NoDisplay=true
+# KDE bug 190522: KDE does not autostart items with NoDisplay=tru...
+# NoDisplay=true
 X-KDE-autostart-phase=1
index d914a4b676567ee52f55ab4cc174bebe45fc1582..ef6a5c453dda75b804f48fa4508a1e2a346c7b61 100644 (file)
@@ -33,17 +33,11 @@ if [ -d "$scriptsdir" ]; then
 fi
 
 # Release the IP if DHCP is used.
-case "`uname -r`" in
-6.*) # 'PID dhclient: em0' => 'em0'
-     for intf in `pgrep -fl dhclient | cut -d" " -f3 | sort | uniq`; do
-        ifconfig "$intf" down
-        ifconfig "$intf" delete
-     done
-     ;;
-*)   # Have dhclient running => release lease
-     ps auxw | grep -q dhclient
-     if [ "$?" -eq 0 ]; then
-        dhclient -r
-     fi
-     ;;
-esac
+for intf in `pgrep -fl dhclient | cut -d" " -f3 | sort | uniq`; do
+   if [ -x /etc/rc.d/netif ]; then
+      /etc/rc.d/netif stop "$intf"
+   else
+      ifconfig "$intf" down
+      ifconfig "$intf" delete
+   fi
+done
index e5f1ac9bba00de840cfbee08a0092d0a19fd1587..d9a1607c1dff0842aaed8f29cdd61a2ead3fe7b3 100644 (file)
@@ -231,7 +231,7 @@ PowerOpsScriptCallback(gpointer _state)
 {
    PowerOpState *state = _state;
 
-   g_assert(state->pid != INVALID_PID);
+   ASSERT(state->pid != INVALID_PID);
 
    if (!ProcMgr_IsAsyncProcRunning(state->pid)) {
       int exitcode;
@@ -320,7 +320,7 @@ PowerOpsScriptCallback(GPid pid,
 {
    PowerOpState *state = _state;
 
-   g_assert(state->pid != INVALID_PID);
+   ASSERT(state->pid != INVALID_PID);
 
    PowerOpsStateChangeDone(_state, status == 0);
    g_spawn_close_pid(state->pid);
@@ -450,7 +450,7 @@ PowerOpsStateChange(RpcInData *data)
             char *tmp;
 
             dfltPath = GuestApp_GetInstallPath();
-            g_assert(dfltPath != NULL);
+            ASSERT(dfltPath != NULL);
 
             /*
              * Before the switch to vmtoolsd, the config file was saved with
index 7c5401ceef60ba837c5072f45e49162e5e8356ba..a6a8475f8adaea7c3f5b325f5c9189e331b1c631 100644 (file)
@@ -45,7 +45,6 @@ typedef struct {
    Bool initialized;                    // TRUE if successfully initialized.
    Bool canSetResolution;               // TRUE if back-end supports Resolution_Set.
    Bool canSetTopology;                 // TRUE if back-end supports DisplayTopology_Set.
-   Bool isWDDM;                         // TRUE if the driver does WDDM.
 } ResolutionInfoType;
 
 
index c57e1ff1ff9d978c574b42bd04c29219dbda416f..974372dee3e2df17fb3cc9c0858e35b2b1723aac 100644 (file)
@@ -412,7 +412,7 @@ ResolutionSetCapabilities(gpointer src,
    ResolutionInfoType *resInfo = &resolutionInfo;
    int resServerCap = 0;
 
-   Debug("%s: enter\n", __FUNCTION__);
+Debug("%s: enter\n", __FUNCTION__);
    if (set) {
       if (!resInfo->initialized) {
          return FALSE;
@@ -427,11 +427,11 @@ ResolutionSetCapabilities(gpointer src,
 
          caps[DPY_TOPO_SET_IDX].value = 2;
          caps[DPY_GLOBAL_OFFSET_IDX].value = 1;
-      }
 #if defined(RESOLUTION_WIN32)
-      Debug("%s: setting DPY_TOPO_MODES_SET_IDX to 1\n", __FUNCTION__);
-      caps[DPY_TOPO_MODES_SET_IDX].value = 1;
+Debug("%s: setting DPY_TOPO_MODES_SET_IDX to 1\n", __FUNCTION__);
+         caps[DPY_TOPO_MODES_SET_IDX].value = 1;
 #endif
+      }
    }
 
    ResolutionServerCapReg(ctx, resServerCap);
index 6b7aaf100d5a71dd872e6ec596e5681734dadc40..bada3a34b6a1b8520a08ac0272be7aaf20826da7 100644 (file)
@@ -25,7 +25,7 @@
 #define G_LOG_DOMAIN "timeSync"
 
 /* sync the time once a minute */
-#define TIME_SYNC_TIME     60000
+#define TIME_SYNC_TIME     60
 /* only PERCENT_CORRECTION percent is corrected everytime */
 #define PERCENT_CORRECTION   50
 
@@ -51,7 +51,7 @@ typedef struct TimeSyncData {
    gboolean    slewCorrection;
    uint32      slewPercentCorrection;
    gint        timeSyncState;
-   uint32      timeSyncPeriod;         /* In milliseconds. */
+   uint32      timeSyncPeriod;         /* In seconds. */
    GSource    *timer;
 } TimeSyncData;
 
@@ -223,6 +223,7 @@ TimeSyncDoSync(Bool slewCorrection,
          }
       } else if (slewCorrection && timeLagCall) {
          int64 slewDiff;
+         int64 timeSyncPeriodUS = data->timeSyncPeriod * 1000000;
 
          /* Don't consider interruptLag during clock slewing. */
          slewDiff = diff - interruptLag;
@@ -230,7 +231,7 @@ TimeSyncDoSync(Bool slewCorrection,
          /* Correct only data->slewPercentCorrection percent error. */
          slewDiff = (data->slewPercentCorrection * slewDiff) / 100;
 
-         if (!System_EnableTimeSlew(slewDiff, data->timeSyncPeriod)) {
+         if (!System_EnableTimeSlew(slewDiff, timeSyncPeriodUS)) {
             g_warning("Unable to slew the guest OS time: %s.\n\n", Msg_ErrString());
             return FALSE;
          }
@@ -272,7 +273,7 @@ ToolsDaemonTimeSyncLoop(gpointer _data)
 {
    TimeSyncData *data = _data;
 
-   g_assert(data != NULL);
+   ASSERT(data != NULL);
 
    if (!TimeSyncDoSync(data->slewCorrection, FALSE, FALSE, data)) {
       g_warning("Unable to synchronize time.\n");
@@ -375,15 +376,15 @@ TimeSyncStartStopLoop(ToolsAppCtx *ctx,
                       TimeSyncData *data,
                       gboolean start)
 {
-   g_assert(data != NULL);
+   ASSERT(data != NULL);
 
    if (start && data->timer == NULL) {
       g_debug("Starting time sync loop.\n");
-      g_debug("New sync period is %d sec.\n", data->timeSyncPeriod / 1000);
+      g_debug("New sync period is %d sec.\n", data->timeSyncPeriod);
       if (!ToolsDaemonTimeSyncLoop(data)) {
          return FALSE;
       }
-      data->timer = g_timeout_source_new(data->timeSyncPeriod);
+      data->timer = g_timeout_source_new(data->timeSyncPeriod * 1000);
       VMTOOLSAPP_ATTACH_SOURCE(ctx, data->timer, ToolsDaemonTimeSyncLoop, data, NULL);
 
 #if defined(_WIN32)
@@ -487,9 +488,11 @@ TimeSyncSetOption(gpointer src,
       /*
        * Try the one-shot time sync if time sync transitions from
        * 'off' to 'on'.
+       * Note that if TOOLSOPTION_SYNCTIME_ENABLE is absent from
+       * vmx config file it is considered to be TRUE.
        */
       if (data->timeSyncState == 0 && start &&
-          g_key_file_get_boolean(ctx->config, "timeSync",
+          g_key_file_get_boolean(ctx->config, "vmsvc",
                                  TOOLSOPTION_SYNCTIME_ENABLE, NULL)) {
          TimeSyncDoSync(data->slewCorrection, TRUE, TRUE, data);
       }
@@ -504,10 +507,15 @@ TimeSyncSetOption(gpointer src,
       g_debug("Daemon: Setting slewCorrection, %d.\n", data->slewCorrection);
    } else if (strcmp(option, TOOLSOPTION_SYNCTIME_PERCENTCORRECTION) == 0) {
       int32 percent;
+      g_debug("Daemon: Setting slewPercentCorrection to %s.\n", value);
       if (!StrUtil_StrToInt(&percent, value)) {
          return FALSE;
       }
-      data->slewPercentCorrection = percent;
+      if (percent <= 0 || percent > 100) {
+         data->slewPercentCorrection = PERCENT_CORRECTION;
+      } else {
+         data->slewPercentCorrection = percent;
+      }
    } else if (strcmp(option, TOOLSOPTION_SYNCTIME_PERIOD) == 0) {
       uint32 period;
 
@@ -521,7 +529,7 @@ TimeSyncSetOption(gpointer src,
        * not running, just remember the new sync period value.
        */
       if (period != data->timeSyncPeriod) {
-         data->timeSyncPeriod = (period > 0) ? period * 1000 : TIME_SYNC_TIME;
+         data->timeSyncPeriod = (period > 0) ? period : TIME_SYNC_TIME;
 
          if (data->timer != NULL) {
             TimeSyncStartStopLoop(ctx, data, FALSE);
@@ -606,7 +614,7 @@ ToolsOnLoad(ToolsAppCtx *ctx)
       { TOOLS_APP_SIGNALS, VMTools_WrapArray(sigs, sizeof *sigs, ARRAYSIZE(sigs)) }
    };
 
-   data->slewCorrection = TRUE;
+   data->slewCorrection = FALSE;
    data->slewPercentCorrection = PERCENT_CORRECTION;
    data->timeSyncState = -1;
    data->timeSyncPeriod = TIME_SYNC_TIME;
index 3334752a8d2425f12c171580cca14fd34e58241d..d2e63060ca1aeca75ec5f0dca655fd1cdc3004ac 100644 (file)
@@ -178,8 +178,8 @@ static void
 VmBackupFinalize(void)
 {
    g_debug("*** %s\n", __FUNCTION__);
-   g_assert(gBackupState != NULL);
-   g_assert(gBackupState->machineState == VMBACKUP_MSTATE_IDLE);
+   ASSERT(gBackupState != NULL);
+   ASSERT(gBackupState->machineState == VMBACKUP_MSTATE_IDLE);
 
    if (gBackupState->currentOp != NULL) {
       VmBackup_Cancel(gBackupState->currentOp);
@@ -196,7 +196,8 @@ VmBackupFinalize(void)
       g_source_destroy(gBackupState->keepAlive);
    }
 
-   free(gBackupState->volumes);
+   g_free(gBackupState->volumes);
+   g_free(gBackupState->snapshots);
    free(gBackupState);
    gBackupState = NULL;
 }
@@ -306,7 +307,7 @@ static gboolean
 VmBackupAsyncCallback(void *clientData)
 {
    g_debug("*** %s\n", __FUNCTION__);
-   g_assert(gBackupState != NULL);
+   ASSERT(gBackupState != NULL);
 
    g_source_unref(gBackupState->timerEvent);
    gBackupState->timerEvent = NULL;
@@ -487,7 +488,7 @@ VmBackupStart(RpcInData *data)
       }
 
       if (data->args[index] != '\0') {
-         gBackupState->volumes = Util_SafeStrdup(data->args + index);
+         gBackupState->volumes = g_strndup(data->args + index, data->argsSize - index);
       }
    }
 
@@ -577,6 +578,9 @@ VmBackupSnapshotDone(RpcInData *data)
                               "Error: unexpected state for snapshot done message.",
                               FALSE);
    } else {
+      if (data->argsSize > 1) {
+         gBackupState->snapshots = g_strndup(data->args + 1, data->argsSize - 1);
+      }
       if (!gSyncProvider->snapshotDone(gBackupState, gSyncProvider->clientData)) {
          VmBackup_SendEvent(VMBACKUP_EVENT_REQUESTOR_ERROR,
                             VMBACKUP_SYNC_ERROR,
index f9e2da31344675123df4e39eeae4a64b24c84605..8e316c3c23a1671d24d2e4b88713f4d7384cc559 100644 (file)
@@ -80,7 +80,8 @@ typedef struct VmBackupState {
    VmBackupOp    *currentOp;
    const char    *currentOpName;
    char          *volumes;
-   guint         pollPeriod;
+   char          *snapshots;
+   guint          pollPeriod;
    GSource       *timerEvent;
    GSource       *keepAlive;
    Bool (*callback)(struct VmBackupState *);
index 55665470f73555c27cc4751f2bd3d088b6f8ddd7..76780187dc39e0a24b5c050cadf3b2afdba4b7c4 100644 (file)
@@ -80,11 +80,5 @@ typedef enum {
    VMBACKUP_UNEXPECTED_ERROR
 } VmBackupStatus;
 
-/* Event name used for communnication between the VSS components. */
-#ifdef _WIN32
-#define VMVSS_RESUME_MSG   TEXT("VmVss_ResumeSnapshotProvider")
-#define VMVSS_LOGGING_EVENT TEXT("VmVss_DebugLoggingEvent")
-#endif
-
 #endif
 
index 6b1ada90a62dee10496e6cb8298949910725b368..a1f238f201570af06ae7cd63681f83956cef562e 100644 (file)
@@ -25,7 +25,7 @@ vmtoolsd_CPPFLAGS += @GMODULE_CPPFLAGS@
 vmtoolsd_CPPFLAGS += @GOBJECT_CPPFLAGS@
 vmtoolsd_CPPFLAGS += @GTHREAD_CPPFLAGS@
 vmtoolsd_CPPFLAGS += -I$(builddir)
-vmtoolsd_CPPFLAGS += -DVMTOOLSD_PLUGIN_ROOT=\"$(pkglibdir)\"
+vmtoolsd_CPPFLAGS += -DVMTOOLSD_PLUGIN_ROOT=\"$(pkglibdir)/plugins\"
 
 vmtoolsd_LDADD =
 vmtoolsd_LDADD += @VMTOOLS_LIBS@
index bb30d46926c3d507d9a98bb7221a94c66cf241f9..6e346663a1abe0ec01cc9c6c98d2cc5e2d14ae00 100644 (file)
@@ -66,8 +66,8 @@ ToolsCoreInitializeDebug(ToolsServiceState *state)
    }
 
    libdata = initFn(&state->ctx, state->debugPlugin);
-   g_assert(libdata != NULL);
-   g_assert(libdata->debugPlugin != NULL);
+   ASSERT(libdata != NULL);
+   ASSERT(libdata->debugPlugin != NULL);
 
    state->debugData = libdata;
 }
@@ -178,52 +178,31 @@ void
 ToolsCore_DumpState(ToolsServiceState *state)
 {
    guint i;
+   const char *providerStates[] = {
+      "idle",
+      "active",
+      "error"
+   };
+
+   ASSERT_ON_COMPILE(ARRAYSIZE(providerStates) == TOOLS_PROVIDER_MAX);
 
    g_message("VM Tools Service '%s':\n", state->name);
    g_message("   Plugin path: %s\n", state->pluginPath);
 
-   if (state->plugins != NULL) {
-      for (i = 0; i < state->plugins->len; i++) {
-         ToolsPlugin *plugin = g_ptr_array_index(state->plugins, i);
-         GArray *regs = (plugin->data != NULL) ? plugin->data->regs : NULL;
-         guint j;
-
-         g_message("   Plugin: %s\n", plugin->data->name);
-
-         if (regs == NULL) {
-            g_message("      No registrations.\n");
-            continue;
-         }
-
-         for (j = 0; j < regs->len; j++) {
-            guint k;
-            ToolsAppReg *reg = &g_array_index(regs, ToolsAppReg, j);
-
-            switch (reg->type) {
-            case TOOLS_APP_GUESTRPC:
-               for (k = 0; k < reg->data->len; k++) {
-                  RpcChannelCallback *cb = &g_array_index(reg->data,
-                                                          RpcChannelCallback,
-                                                          k);
-                  g_message("      RPC callback: %s\n", cb->name);
-               }
-               break;
-
-            case TOOLS_APP_SIGNALS:
-               for (k = 0; k < reg->data->len; k++) {
-                  ToolsPluginSignalCb *sig = &g_array_index(reg->data,
-                                                            ToolsPluginSignalCb,
-                                                            k);
-                  g_message("      Signal callback: %s\n", sig->signame);
-               }
-               break;
-            }
-         }
+   for (i = 0; i < state->providers->len; i++) {
+      ToolsAppProviderReg *prov = &g_array_index(state->providers,
+                                                 ToolsAppProviderReg,
+                                                 i);
+      g_message("   App provider: %s (%s)\n",
+                prov->prov->name,
+                providerStates[prov->state]);
+      if (prov->prov->dumpState != NULL) {
+         prov->prov->dumpState(&state->ctx, prov->prov, NULL);
       }
-   } else {
-      g_message("   No plugins loaded.");
    }
 
+   ToolsCore_DumpPluginInfo(state);
+
    g_signal_emit_by_name(state->ctx.serviceObj,
                          TOOLS_CORE_SIG_DUMP_STATE,
                          &state->ctx);
@@ -274,6 +253,7 @@ ToolsCore_Setup(ToolsServiceState *state)
 
    /* Initializes the app context. */
    gctx = g_main_context_default();
+   state->ctx.version = TOOLS_CORE_API_V1;
    state->ctx.name = state->name;
    state->ctx.errorCode = EXIT_SUCCESS;
    state->ctx.mainLoop = g_main_loop_new(gctx, TRUE);
index 688988e9b86c2b00158c091018313005722702db..ded73ff047708cb96f4162b24c2bf2f0521c241c 100644 (file)
@@ -123,9 +123,12 @@ main(int argc,
        * was used, or things may not work as expected.
        */
       if (!g_path_is_absolute(argv[0])) {
-         char *cwd = File_Cwd(NULL);
-         char *abs = g_strdup_printf("%s%c%s", cwd, DIRSEPC, argv[0]);
-         vm_free(cwd);
+         gchar *abs = g_find_program_in_path(argv[0]);
+         if (abs == NULL) {
+            char *cwd = File_Cwd(NULL);
+            abs = g_strdup_printf("%s%c%s", cwd, DIRSEPC, argv[0]);
+            vm_free(cwd);
+         }
          argv[0] = abs;
       }
 
index 797b01979a401ab84a5735d966a7b8b46df4535b..fc8f083f974bc0fb4895b1d93c3bc6b950549c0f 100644 (file)
 
 
 #ifdef USE_APPLOADER
-static Bool (*LoadDependencies)(char *libName);
+static Bool (*LoadDependencies)(char *libName, Bool useShipped);
 #endif
 
+typedef void (*PluginDataCallback)(ToolsServiceState *state,
+                                   ToolsPluginData *plugin);
+
+typedef void (*PluginAppRegCallback)(ToolsServiceState *state,
+                                     ToolsPluginData *plugin,
+                                     ToolsAppType type,
+                                     ToolsAppProviderReg *preg,
+                                     gpointer reg);
+
+
+/**
+ * State dump callback for application registration information.
+ *
+ * @param[in]  state The service state.
+ * @param[in]  plugin   The plugin information.
+ * @param[in]  type     Application type.
+ * @param[in]  preg     Provider information.
+ * @param[in]  reg      Application registration.
+ */
+
+static void
+ToolsCoreDumpAppInfo(ToolsServiceState *state,
+                     ToolsPluginData *plugin,
+                     ToolsAppType type,
+                     ToolsAppProviderReg *preg,
+                     gpointer reg)
+{
+   if (preg != NULL) {
+      if (preg->prov->dumpState != NULL) {
+         preg->prov->dumpState(&state->ctx, preg->prov, reg);
+      } else {
+         g_message("      App type %u (no provider info).\n", type);
+      }
+    } else {
+      g_message("      App type %u (no provider).\n", type);
+   }
+}
+
+
+/**
+ * State dump callback for generic plugin information.
+ *
+ * @param[in]  state    The service state.
+ * @param[in]  plugin   The plugin information.
+ */
+
+static void
+ToolsCoreDumpPluginInfo(ToolsServiceState *state,
+                        ToolsPluginData *plugin)
+{
+   g_message("   Plugin: %s\n", plugin->name);
+
+   if (plugin->regs == NULL) {
+      g_message("      No registrations.\n");
+   }
+}
+
+
+/**
+ * State dump callback for GuestRPC applications.
+ *
+ * @param[in]  ctx   The application context.
+ * @param[in]  prov  Unused.
+ * @param[in]  reg   The application registration data.
+ */
+
+static void
+ToolsCoreDumpRPC(ToolsAppCtx *ctx,
+                 ToolsAppProvider *prov,
+                 gpointer reg)
+{
+   if (reg != NULL) {
+      RpcChannelCallback *cb = reg;
+      g_message("      RPC callback: %s\n", cb->name);
+   }
+}
+
+
+/**
+ * State dump callback for signal connections.
+ *
+ * @param[in]  ctx   The application context.
+ * @param[in]  prov  Unused.
+ * @param[in]  reg   The application registration data.
+ */
+
+static void
+ToolsCoreDumpSignal(ToolsAppCtx *ctx,
+                    ToolsAppProvider *prov,
+                    gpointer reg)
+{
+   if (reg != NULL) {
+      ToolsPluginSignalCb *sig = reg;
+      g_message("      Signal callback: %s\n", sig->signame);
+   }
+}
+
+
+/**
+ * Callback to register applications with the given provider.
+ *
+ * @param[in]  state    The service state.
+ * @param[in]  plugin   The plugin information.
+ * @param[in]  type     Application type.
+ * @param[in]  preg     Provider information.
+ * @param[in]  reg      Application registration.
+ */
+
+static void
+ToolsCoreRegisterApp(ToolsServiceState *state,
+                     ToolsPluginData *plugin,
+                     ToolsAppType type,
+                     ToolsAppProviderReg *preg,
+                     gpointer reg)
+{
+   if (preg == NULL) {
+      g_warning("Plugin %s wants to register app of type %d but no "
+                "provider was found.\n", plugin->name, type);
+      return;
+   }
+
+   if (preg->state == TOOLS_PROVIDER_ERROR) {
+      g_warning("Plugin %s wants to register app of type %d but the "
+                "provider failed to activate.\n", plugin->name, type);
+      return;
+   }
+
+   /*
+    * Register the app with the provider, activating it if necessary. If
+    * it fails to activate, tag it so we don't try again.
+    */
+   if (preg->state == TOOLS_PROVIDER_IDLE) {
+      if (preg->prov->activate != NULL) {
+         GError *err = NULL;
+         preg->prov->activate(&state->ctx, preg->prov, &err);
+         if (err != NULL) {
+            g_warning("Error activating provider %s: %s.\n",
+                      preg->prov->name, err->message);
+            preg->state = TOOLS_PROVIDER_ERROR;
+            g_clear_error(&err);
+            return;
+         }
+      }
+      preg->state = TOOLS_PROVIDER_ACTIVE;
+   }
+
+   preg->prov->registerApp(&state->ctx, preg->prov, reg);
+}
+
+
+/**
+ * Callback to register application providers.
+ *
+ * @param[in]  state    The service state.
+ * @param[in]  plugin   The plugin information.
+ * @param[in]  type     Application type.
+ * @param[in]  preg     Provider information.
+ * @param[in]  reg      Application registration.
+ */
+
+static void
+ToolsCoreRegisterProvider(ToolsServiceState *state,
+                          ToolsPluginData *plugin,
+                          ToolsAppType type,
+                          ToolsAppProviderReg *preg,
+                          gpointer reg)
+{
+   if (type == TOOLS_APP_PROVIDER) {
+      ToolsAppProvider *prov = reg;
+      ToolsAppProviderReg newreg = { prov, TOOLS_PROVIDER_IDLE };
+
+      /* Assert that no two providers choose the same app type. */
+      ASSERT(preg == NULL);
+
+      ASSERT(prov->name != NULL);
+      ASSERT(prov->registerApp != NULL);
+      g_array_append_val(state->providers, newreg);
+   }
+}
+
+
+/**
+ * Iterates through the list of plugins, and through each plugin's app
+ * registration data, calling the appropriate callback for each piece
+ * of data.
+ *
+ * One of the two callback arguments must be provided.
+ *
+ * @param[in]  state       Service state.
+ * @param[in]  pluginCb    Callback called for each plugin data instance.
+ * @param[in]  appRegCb    Callback called for each application registration.
+ */
+
+static void
+ToolsCoreForEachPlugin(ToolsServiceState *state,
+                       PluginDataCallback pluginCb,
+                       PluginAppRegCallback appRegCb)
+{
+   guint i;
+
+   ASSERT(pluginCb != NULL || appRegCb != NULL);
+
+   for (i = 0; i < state->plugins->len; i++) {
+      ToolsPlugin *plugin = g_ptr_array_index(state->plugins, i);
+      GArray *regs = (plugin->data != NULL) ? plugin->data->regs : NULL;
+      guint j;
+
+      if (pluginCb != NULL) {
+         pluginCb(state, plugin->data);
+      }
+
+      if (regs == NULL || appRegCb == NULL) {
+         continue;
+      }
+
+      for (j = 0; j < regs->len; j++) {
+         guint k;
+         guint provIdx = -1;
+         ToolsAppReg *reg = &g_array_index(regs, ToolsAppReg, j);
+         ToolsAppProviderReg *preg = NULL;
+
+         /* Find the provider for the desired reg type. */
+         for (k = 0; k < state->providers->len; k++) {
+            ToolsAppProviderReg *tmp = &g_array_index(state->providers,
+                                                      ToolsAppProviderReg,
+                                                      k);
+            if (tmp->prov->regType == reg->type) {
+               preg = tmp;
+               provIdx = k;
+               break;
+            }
+         }
+
+         for (k = 0; k < reg->data->len; k++) {
+            gpointer appdata = &reg->data->data[preg->prov->regSize * k];
+            appRegCb(state, plugin->data, reg->type, preg, appdata);
+         }
+      }
+   }
+}
+
+
+/**
+ * Registration callback for GuestRPC applications.
+ *
+ * @param[in]  ctx   The application context.
+ * @param[in]  prov  Unused.
+ * @param[in]  reg   The application registration data.
+ */
+
+static void
+ToolsCoreRegisterRPC(ToolsAppCtx *ctx,
+                     ToolsAppProvider *prov,
+                     gpointer reg)
+{
+   RpcChannel_RegisterCallback(ctx->rpc, reg);
+}
+
+
+/**
+ * Registration callback for signal connections.
+ *
+ * @param[in]  ctx   The application context.
+ * @param[in]  prov  Unused.
+ * @param[in]  reg   The application registration data.
+ */
+
+static void
+ToolsCoreRegisterSignal(ToolsAppCtx *ctx,
+                        ToolsAppProvider *prov,
+                        gpointer reg)
+{
+   ToolsPluginSignalCb *sig = reg;
+   g_signal_connect(ctx->serviceObj,
+                    sig->signame,
+                    sig->callback,
+                    sig->clientData);
+}
+
 
 /**
  * Compares two strings. To be used with g_ptr_array_sort.
@@ -54,6 +333,23 @@ ToolsCoreStrPtrCompare(gconstpointer _str1,
 }
 
 
+/**
+ * State dump callback for logging information about loaded plugins.
+ *
+ * @param[in]  state    The service state.
+ */
+
+void
+ToolsCore_DumpPluginInfo(ToolsServiceState *state)
+{
+   if (state->plugins == NULL) {
+      g_message("   No plugins loaded.");
+   } else {
+      ToolsCoreForEachPlugin(state, ToolsCoreDumpPluginInfo, ToolsCoreDumpAppInfo);
+   }
+}
+
+
 /**
  * Loads all plugins present in the plugin directory. If the plugin path
  * is NULL, then default directories are used in case the service is either
@@ -158,7 +454,7 @@ ToolsCore_LoadPlugins(ToolsServiceState *state)
       }
 
 #ifdef USE_APPLOADER
-      if (!LoadDependencies(path)) {
+      if (!LoadDependencies(path, FALSE)) {
          g_warning("Loading of library dependencies for %s failed.\n", entry);
          goto next;
       }
@@ -226,59 +522,54 @@ exit:
 void
 ToolsCore_RegisterPlugins(ToolsServiceState *state)
 {
-   guint i;
+   ToolsAppProvider *fakeProv;
+   ToolsAppProviderReg fakeReg;
 
    if (state->plugins == NULL) {
       return;
    }
 
-   for (i = 0; i < state->plugins->len; i++) {
-      ToolsPlugin *plugin = g_ptr_array_index(state->plugins, i);
-      GArray *regs = (plugin->data != NULL) ? plugin->data->regs : NULL;
-      guint j;
+   /*
+    * Create two "fake" app providers for the functionality provided by
+    * vmtoolsd (GuestRPC channel, glib signals).
+    */
+   state->providers = g_array_new(FALSE, TRUE, sizeof (ToolsAppProviderReg));
+
+   if (state->ctx.rpc != NULL) {
+      fakeProv = g_malloc0(sizeof *fakeProv);
+      fakeProv->regType = TOOLS_APP_GUESTRPC;
+      fakeProv->regSize = sizeof (RpcChannelCallback);
+      fakeProv->name = "GuestRPC";
+      fakeProv->registerApp = ToolsCoreRegisterRPC;
+      fakeProv->dumpState = ToolsCoreDumpRPC;
+
+      fakeReg.prov = fakeProv;
+      fakeReg.state = TOOLS_PROVIDER_ACTIVE;
+      g_array_append_val(state->providers, fakeReg);
+   }
 
-      if (regs == NULL) {
-         continue;
-      }
+   fakeProv = g_malloc0(sizeof *fakeProv);
+   fakeProv->regType = TOOLS_APP_SIGNALS;
+   fakeProv->regSize = sizeof (ToolsPluginSignalCb);
+   fakeProv->name = "Signals";
+   fakeProv->registerApp = ToolsCoreRegisterSignal;
+   fakeProv->dumpState = ToolsCoreDumpSignal;
 
-      for (j = 0; j < regs->len; j++) {
-         guint k;
-         ToolsAppReg *reg = &g_array_index(regs, ToolsAppReg, j);
+   fakeReg.prov = fakeProv;
+   fakeReg.state = TOOLS_PROVIDER_ACTIVE;
+   g_array_append_val(state->providers, fakeReg);
 
-         switch (reg->type) {
-         case TOOLS_APP_GUESTRPC:
-            ASSERT(reg->data != NULL);
-            if (state->ctx.rpc == NULL) {
-               g_warning("Plugin '%s' asked to register a Guest RPC handler, "
-                         "but there's no RPC channel.\n", plugin->data->name);
-            } else {
-               for (k = 0; k < reg->data->len; k++) {
-                  RpcChannelCallback *cb = &g_array_index(reg->data,
-                                                          RpcChannelCallback,
-                                                          k);
-                  RpcChannel_RegisterCallback(state->ctx.rpc, cb);
-               }
-            }
-            break;
-
-         case TOOLS_APP_SIGNALS:
-            ASSERT(reg->data != NULL);
-            for (k = 0; k < reg->data->len; k++) {
-               ToolsPluginSignalCb *sig = &g_array_index(reg->data,
-                                                         ToolsPluginSignalCb,
-                                                         k);
-               g_signal_connect(state->ctx.serviceObj,
-                                sig->signame,
-                                sig->callback,
-                                sig->clientData);
-            }
-            break;
+   /*
+    * First app providers need to be identified, so that we know that they're
+    * available for use by plugins who need them.
+    */
+   ToolsCoreForEachPlugin(state, NULL, ToolsCoreRegisterProvider);
 
-         default:
-            NOT_IMPLEMENTED();
-         }
-      }
-   }
+   /*
+    * Now that we know all app providers, register all the apps, activating
+    * individual app providers as necessary.
+    */
+   ToolsCoreForEachPlugin(state, NULL, ToolsCoreRegisterApp);
 }
 
 
@@ -298,6 +589,7 @@ ToolsCore_RegisterPlugins(ToolsServiceState *state)
 void
 ToolsCore_UnloadPlugins(ToolsServiceState *state)
 {
+   guint i;
    GArray *pcaps = NULL;
 
    if (state->plugins == NULL) {
@@ -317,6 +609,25 @@ ToolsCore_UnloadPlugins(ToolsServiceState *state)
 
    g_signal_emit_by_name(state->ctx.serviceObj, TOOLS_CORE_SIG_SHUTDOWN, &state->ctx);
 
+   /*
+    * Stop all app providers, and free the memory we allocated for the two
+    * internal app providers.
+    */
+   for (i = 0; i < state->providers->len; i++) {
+       ToolsAppProviderReg *preg = &g_array_index(state->providers,
+                                                  ToolsAppProviderReg,
+                                                  i);
+
+       if (preg->prov->shutdown != NULL) {
+          preg->prov->shutdown(&state->ctx, preg->prov);
+       }
+
+      if (preg->prov->regType == TOOLS_APP_GUESTRPC ||
+          preg->prov->regType == TOOLS_APP_SIGNALS) {
+         g_free(preg->prov);
+      }
+   }
+
    while (state->plugins->len > 0) {
       ToolsPlugin *plugin = g_ptr_array_index(state->plugins, state->plugins->len - 1);
       GArray *regs = (plugin->data != NULL) ? plugin->data->regs : NULL;
@@ -339,6 +650,9 @@ ToolsCore_UnloadPlugins(ToolsServiceState *state)
       g_free(plugin);
    }
 
+   g_array_free(state->providers, TRUE);
+   state->providers = NULL;
+
    g_ptr_array_free(state->plugins, TRUE);
    state->plugins = NULL;
 }
index 631824f9af90dca50af323aa48a340d4db46f518..3e12654c618717e0330d0f2f86280b7cba78979b 100644 (file)
@@ -45,6 +45,22 @@ typedef struct ToolsPlugin {
    ToolsPluginData  *data;
 } ToolsPlugin;
 
+/** State of app providers. */
+typedef enum {
+   TOOLS_PROVIDER_IDLE,
+   TOOLS_PROVIDER_ACTIVE,
+   TOOLS_PROVIDER_ERROR,
+
+   /* Keep this as the last one, always. */
+   TOOLS_PROVIDER_MAX
+} ToolsAppProviderState;
+
+/** Defines the internal app provider data. */
+typedef struct ToolsAppProviderReg {
+   ToolsAppProvider       *prov;
+   ToolsAppProviderState   state;
+} ToolsAppProviderReg;
+
 /** Defines internal service state. */
 typedef struct ToolsServiceState {
    gchar         *name;
@@ -63,6 +79,7 @@ typedef struct ToolsServiceState {
    gchar         *debugPlugin;
    RpcDebugLibData  *debugData;
    ToolsAppCtx    ctx;
+   GArray        *providers;
 } ToolsServiceState;
 
 
@@ -74,6 +91,9 @@ ToolsCore_ParseCommandLine(ToolsServiceState *state,
 void
 ToolsCore_Cleanup(ToolsServiceState *state);
 
+void
+ToolsCore_DumpPluginInfo(ToolsServiceState *state);
+
 void
 ToolsCore_DumpState(ToolsServiceState *state);
 
index 5406d19f7e5faca8e0075c632dfa67d503adf9df..3f85401f80d66a98c07ed1cd66b50ded330ec3dc 100644 (file)
@@ -58,7 +58,7 @@ ToolsCoreCheckReset(struct RpcChannel *chan,
       gchar *msg;
 
       app = ToolsCore_GetTcloName(state);
-      g_assert(app != NULL);
+      ASSERT(app != NULL);
 
       msg = g_strdup_printf("vmx.capability.unified_loop %s", app);
       if (!RpcChannel_Send(state->ctx.rpc, msg, strlen(msg) + 1, NULL, NULL)) {
@@ -229,7 +229,7 @@ ToolsCore_InitRpc(ToolsServiceState *state)
    const gchar *app;
    GMainContext *mainCtx = g_main_loop_get_context(state->ctx.mainLoop);
 
-   g_assert(state->ctx.rpc == NULL);
+   ASSERT(state->ctx.rpc == NULL);
 
    if (state->debugPlugin != NULL) {
       app = "debug";
@@ -251,7 +251,7 @@ ToolsCore_InitRpc(ToolsServiceState *state)
 
       state->ctx.rpc = RpcChannel_NewBackdoorChannel(mainCtx);
       app = ToolsCore_GetTcloName(state);
-      g_assert(app != NULL);
+      ASSERT(app != NULL);
    }
 
    RpcChannel_Setup(state->ctx.rpc,
index 2580ca4123ebaaa6938a2f53a773b7f24be90a47..33534bba5f248c8f2d80770dccc07a5a60332ebd 100644 (file)
@@ -1,3 +1,4 @@
+
 /*********************************************************
  * Copyright (C) 2008 VMware, Inc. All rights reserved.
  *
@@ -35,7 +36,7 @@ VM_EMBED_VERSION(TOOLBOXCMD_VERSION_STRING);
 
 
 typedef int (*ToolboxCmdFunc)(char **argv, int argc);
-typedef void (*ToolboxHelpFunc)(char *progName);
+typedef void (*ToolboxHelpFunc)(const char *progName);
 
 
 /*
@@ -43,13 +44,14 @@ typedef void (*ToolboxHelpFunc)(char *progName);
  */
 
 const typedef struct CmdTable {
-   const char *command;                /* The name of the command. */
-   ToolboxCmdFunc func;                /* The function to execute. */
-   Bool requireRoot;           /* Indicates whether root is required. */
-   ToolboxHelpFunc helpFunc;   /* The help function associated with the command. */
+   const char *command;       /* The name of the command. */
+   ToolboxCmdFunc func;       /* The function to execute. */
+   Bool requireArguments;     /* The function requires arguments. */
+   Bool requireRoot;          /* Indicates whether root is required. */
+   ToolboxHelpFunc helpFunc;  /* The help function associated with the command. */
 } CmdTable;
 
-static int quiet_flag; /* Flag set by `--quiet'. */
+static Bool quiet_flag; /* Flag set by `--quiet'. */
 
 /*
  * Sadly, our home-brewed implementation of getopt() doesn't come with an
@@ -78,14 +80,13 @@ static int DiskCommand(char **argv, int argc);
 static int StatCommand(char **argv, int argc);
 static int ScriptCommand(char **argv, int argc);
 static int TimeSyncCommand(char **argv, int argc);
-static void DeviceHelp(char *progName);
-static void DiskHelp(char *progName);
-static void ScriptHelp(char *progName);
-static void StatHelp(char *progName);
-static void TimeSyncHelp(char *progName);
-static void ToolboxCmdHelp(char *progName);
+static void DeviceHelp(const char *progName);
+static void DiskHelp(const char *progName);
+static void ScriptHelp(const char *progName);
+static void StatHelp(const char *progName);
+static void TimeSyncHelp(const char *progName);
+static void ToolboxCmdHelp(const char *progName);
 static CmdTable *ParseCommand(char **argv, int argc);
-static Bool CheckArgumentLength(char **argv, int argc);
 
 
 /*
@@ -93,43 +94,62 @@ static Bool CheckArgumentLength(char **argv, int argc);
  * Must go after function declarations
  */
 static CmdTable commands[] = {
-   { "timesync", TimeSyncCommand, FALSE, TimeSyncHelp},
-   { "script", ScriptCommand, TRUE, ScriptHelp},
-   { "disk", DiskCommand, TRUE, DiskHelp},
-   { "stat", StatCommand, FALSE, StatHelp},
-   { "device", DeviceCommand, FALSE, DeviceHelp},
-   { "help", HelpCommand, FALSE, ToolboxCmdHelp},
-   { NULL, } };
+   { "timesync", TimeSyncCommand, TRUE, FALSE, TimeSyncHelp},
+   { "script", ScriptCommand, FALSE /* We will handle argument checks ourselves */,
+      TRUE, ScriptHelp},
+   { "disk", DiskCommand, TRUE, TRUE, DiskHelp},
+   { "stat", StatCommand, TRUE, FALSE, StatHelp},
+   { "device", DeviceCommand, TRUE, FALSE, DeviceHelp},
+   { "help", HelpCommand, FALSE, FALSE, ToolboxCmdHelp},
+};
 
 
 /*
  *-----------------------------------------------------------------------------
  *
- * CheckArgumentLength --
+ * ToolboxMissingEntityError --
  *
- *      Makes sure that the program receives at least one subcommand.
+ *      Print out error message regarding missing argument.
  *
  * Results:
- *      TRUE if there is at least one subcommand.
- *      FALSE otherwise.
+ *      None.
  *
  * Side effects:
- *      Prints to stderr if the subcommand is missing.
+ *      None.
  *
  *-----------------------------------------------------------------------------
  */
 
-static Bool
-CheckArgumentLength(char **argv, // IN: The command line arguments.
-                    int argc)    // IN: The length of the command line argumensts
+static void
+ToolboxMissingEntityError(const char *name,     // IN: command name (argv[0])
+                          const char *entity)   // IN: what is missing
 {
-   if (++optind < argc) {
-      return TRUE;
-   } else {
-      fprintf(stderr, "Missing command\n");
-      return FALSE;
-   }
+   fprintf(stderr, "%s: Missing %s\n", name, entity);
+}
 
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ToolboxUnknownEntityError --
+ *
+ *      Print out error message regarding unknown argument.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+ToolboxUnknownEntityError(const char *name,    // IN: command name (argv[0])
+                          const char *entity,  // IN: what is unknown
+                          const char *str)     // IN: errorneous string
+{
+   fprintf(stderr, "%s: Unknown %s '%s'\n", name, entity, str);
 }
 
 
@@ -150,7 +170,7 @@ CheckArgumentLength(char **argv, // IN: The command line arguments.
  */
 
 static void
-DeviceHelp(char *progName) // IN: The name of the program obtained from argv[0]
+DeviceHelp(const char *progName) // IN: The name of the program obtained from argv[0]
 {
    printf("device: functions related to the virtual machine's hardware devices\n"
           "Usage: %s device <subcommand> [args]\n"
@@ -180,19 +200,19 @@ DeviceHelp(char *progName) // IN: The name of the program obtained from argv[0]
  */
 
 static void
-ToolboxCmdHelp(char *progName)
+ToolboxCmdHelp(const char *progName)
 {
    printf("Usage: %s <command> [options] [subcommand]\n"
           "Type \'%s help <command>\' for help on a specific command.\n"
-          "Type \'%s --version' to see the Vmware Tools version.\n"
-          "Use --quiet to suppress stdout output.\n"
+          "Type \'%s -v' to see the Vmware Tools version.\n"
+          "Use '-q' option to suppress stdout output.\n"
           "Most commands take a subcommand.\n\n"
           "Available commands:\n"
-          "   timesync\n"
           "   device\n"
-          "   script\n"
           "   disk\n"
+          "   script\n"
           "   stat\n"
+          "   timesync\n"
           "\n"
           "For additional information please visit http://www.vmware.com/support/\n\n",
           progName, progName, progName);
@@ -216,7 +236,7 @@ ToolboxCmdHelp(char *progName)
  */
 
 static void
-TimeSyncHelp(char *progName) // IN: The name of the program obtained from argv[0]
+TimeSyncHelp(const char *progName) // IN: The name of the program obtained from argv[0]
 {
    printf("timesync: functions for controlling time synchronization on the guest OS\n"
           "Usage: %s timesync <subcommand>\n\n"
@@ -244,10 +264,10 @@ TimeSyncHelp(char *progName) // IN: The name of the program obtained from argv[0
  */
 
 static void
-ScriptHelp(char *progName) // IN: The name of the program obtained from argv[0]
+ScriptHelp(const char *progName) // IN: The name of the program obtained from argv[0]
 {
    printf("script: control the scripts run in response to power operations\n"
-          "Usage: %s script <power|resume|suspend|shutdown> <subcomamnd> [args]\n\n"
+          "Usage: %s script <power|resume|suspend|shutdown> <subcommand> [args]\n\n"
           "Subcommands:\n"
           "   enable: enable the given script and restore its path to the default\n"
           "   disable: disable the given script\n"
@@ -274,7 +294,7 @@ ScriptHelp(char *progName) // IN: The name of the program obtained from argv[0]
  */
 
 static void
-DiskHelp(char *progName) // IN: The name of the program obtained from argv[0]
+DiskHelp(const char *progName) // IN: The name of the program obtained from argv[0]
 {
    printf("disk: perform disk shrink operations\n"
           "Usage: %s disk <subcommand> [args]\n\n"
@@ -302,7 +322,7 @@ DiskHelp(char *progName) // IN: The name of the program obtained from argv[0]
  */
 
 static void
-StatHelp(char *progName) // IN: The name of the program obtained from argv[0]
+StatHelp(const char *progName) // IN: The name of the program obtained from argv[0]
 {
    printf("stat: print useful guest and host information\n"
           "Usage: %s stat <subcommand>\n\n"
@@ -342,19 +362,23 @@ static int
 HelpCommand(char **argv, // IN: Command line arguments
             int argc)    // IN: Length of argv
 {
-   if (CheckArgumentLength(argv, argc)) {
-      int i = 0;
-      while (commands[i].command != 0) {
-        if (toolbox_strcmp(commands[i].command, argv[optind]) == 0) {
+   int retval = EXIT_SUCCESS;
+
+   if (++optind < argc) {
+      int i;
+
+      for (i = 0; i < ARRAYSIZE(commands); i++) {
+         if (toolbox_strcmp(commands[i].command, argv[optind]) == 0) {
             commands[i].helpFunc(argv[0]);
             return EXIT_SUCCESS;
          }
-        i++;
       }
-      fprintf(stderr, "Unknown subcommand\n");
+      ToolboxUnknownEntityError(argv[0], "subcommand", argv[optind]);
+      retval = EX_USAGE;
    }
+
    ToolboxCmdHelp(argv[0]);
-   return EX_USAGE;
+   return retval;
 }
 
 
@@ -367,7 +391,7 @@ HelpCommand(char **argv, // IN: Command line arguments
  *
  * Results:
  *      Returns EXIT_SUCCESS on success.
- *      Returns ther exit code on errors.
+ *      Returns the exit code on errors.
  *
  * Side effects:
  *      Might enable or disable a device.
@@ -377,31 +401,31 @@ HelpCommand(char **argv, // IN: Command line arguments
 
 static int
 DeviceCommand(char **argv, // IN: Command line arguments
-              int argc)    // IN: Length of command line argumenst
+              int argc)    // IN: Length of command line arguments
 {
-   if (CheckArgumentLength(argv, argc)) {
-      if (toolbox_strcmp(argv[optind], "list") == 0) {
-         return Devices_ListDevices();
-      } else {
-        char *subcommand = argv[optind++];
-        if (optind < argc) {
-           if (toolbox_strcmp(subcommand, "status") == 0) {
-              return Devices_DeviceStatus(argv[optind]);
-           } else if (toolbox_strcmp(subcommand, "enable") == 0) {
-              return Devices_EnableDevice(argv[optind], quiet_flag);
-           } else if (toolbox_strcmp(subcommand, "disable") == 0) {
-              return Devices_DisableDevice(argv[optind], quiet_flag);
-           } else {
-              fprintf(stderr, "Unknown subcommand\n");
-
-           }
-        } else {
-           fprintf(stderr, "Missing device name\n");
-
-        }
+   char *subcommand = argv[optind];
+   Bool haveDeviceArg = optind + 1 < argc;
+
+   if (toolbox_strcmp(subcommand, "list") == 0) {
+      return Devices_ListDevices();
+   } else if (toolbox_strcmp(subcommand, "status") == 0) {
+      if (haveDeviceArg) {
+         return Devices_DeviceStatus(argv[optind + 1]);
+      }
+   } else if (toolbox_strcmp(subcommand, "enable") == 0) {
+      if (haveDeviceArg) {
+         return Devices_EnableDevice(argv[optind + 1], quiet_flag);
       }
+   } else if (toolbox_strcmp(subcommand, "disable") == 0) {
+      if (haveDeviceArg) {
+         return Devices_DisableDevice(argv[optind + 1], quiet_flag);
+      }
+   } else {
+      ToolboxUnknownEntityError(argv[0], "subcommand", subcommand);
+      return EX_USAGE;
    }
-   DeviceHelp(argv[0]);
+
+   ToolboxMissingEntityError(argv[0], "device name");
    return EX_USAGE;
 }
 
@@ -427,22 +451,17 @@ static int
 DiskCommand(char **argv, // IN: command line arguments
             int argc)    // IN: The length of the command line arguments
 {
-   if (CheckArgumentLength(argv, argc)) {
-      if (toolbox_strcmp(argv[optind], "list") == 0) {
-        return Shrink_List();
-      } else if (toolbox_strcmp(argv[optind], "shrink") == 0) {
-        optind++; // Position optind at the mountpoint
-        if (optind < argc) {
-           return Shrink_DoShrink(argv[optind], quiet_flag);
-        } else {
-           fprintf(stderr, "Missing mount point\n");
-        }
+   if (toolbox_strcmp(argv[optind], "list") == 0) {
+      return Shrink_List();
+   } else if (toolbox_strcmp(argv[optind], "shrink") == 0) {
+      if (++optind >= argc) {
+         ToolboxMissingEntityError(argv[0], "mount point");
       } else {
-        fprintf(stderr, "Unknown subcommand\n");
-
+         return Shrink_DoShrink(argv[optind], quiet_flag);
       }
+   } else {
+      ToolboxUnknownEntityError(argv[0], "subcommand", argv[optind]);
    }
-   DiskHelp(argv[0]);
    return EX_USAGE;
 }
 
@@ -465,36 +484,33 @@ DiskCommand(char **argv, // IN: command line arguments
  */
 
 static int
-StatCommand(char **argv, // IN: Comand line arguments
+StatCommand(char **argv, // IN: Command line arguments
             int argc)    // IN: Length of command line arguments
 {
-   if (CheckArgumentLength(argv, argc)) {
-      if (toolbox_strcmp(argv[optind], "memory") == 0) {
-        return Stat_MemorySize();
-      } else if (toolbox_strcmp(argv[optind], "hosttime") == 0) {
-        return Stat_HostTime();
-      } else if (toolbox_strcmp(argv[optind], "sessionid") == 0) {
-        return Stat_GetSessionID();
-      } else if (toolbox_strcmp(argv[optind], "balloon") == 0) {
-        return Stat_GetMemoryBallooned();
-      } else if (toolbox_strcmp(argv[optind], "swap") == 0) {
-        return Stat_GetMemorySwapped();
-      } else if (toolbox_strcmp(argv[optind], "memlimit") == 0) {
-        return Stat_GetMemoryLimit();
-      } else if (toolbox_strcmp(argv[optind], "memres") == 0) {
-        return Stat_GetMemoryReservation();
-      } else if (toolbox_strcmp(argv[optind], "cpures") == 0) {
-        return Stat_GetCpuReservation();
-      } else if (toolbox_strcmp(argv[optind], "cpulimit") == 0) {
-        return Stat_GetCpuLimit();
-      } else if (toolbox_strcmp(argv[optind], "speed") == 0) {
-        return Stat_ProcessorSpeed();
-      } else {
-        fprintf(stderr, "Unknown subcommand\n");
-      }
+   if (toolbox_strcmp(argv[optind], "memory") == 0) {
+      return Stat_MemorySize();
+   } else if (toolbox_strcmp(argv[optind], "hosttime") == 0) {
+      return Stat_HostTime();
+   } else if (toolbox_strcmp(argv[optind], "sessionid") == 0) {
+      return Stat_GetSessionID();
+   } else if (toolbox_strcmp(argv[optind], "balloon") == 0) {
+      return Stat_GetMemoryBallooned();
+   } else if (toolbox_strcmp(argv[optind], "swap") == 0) {
+      return Stat_GetMemorySwapped();
+   } else if (toolbox_strcmp(argv[optind], "memlimit") == 0) {
+      return Stat_GetMemoryLimit();
+   } else if (toolbox_strcmp(argv[optind], "memres") == 0) {
+      return Stat_GetMemoryReservation();
+   } else if (toolbox_strcmp(argv[optind], "cpures") == 0) {
+      return Stat_GetCpuReservation();
+   } else if (toolbox_strcmp(argv[optind], "cpulimit") == 0) {
+      return Stat_GetCpuLimit();
+   } else if (toolbox_strcmp(argv[optind], "speed") == 0) {
+      return Stat_ProcessorSpeed();
+   } else {
+      ToolboxUnknownEntityError(argv[0], "subcommand", argv[optind]);
+      return EX_USAGE;
    }
-   StatHelp(argv[0]);
-   return EX_USAGE;
 }
 
 
@@ -519,37 +535,43 @@ static int
 ScriptCommand(char **argv, // IN: command line arguments.
               int argc)    // IN: the length of the command line arguments.
 {
-   if (CheckArgumentLength(argv, argc)) {
-      char* apm = argv[optind++];
+   const char *apm;
 
-      if (optind >= argc) {
-        fprintf(stderr, "Missing subcommand\n");
-        return EX_USAGE;
-      }
+   if (++optind >= argc) {
+      ToolboxMissingEntityError(argv[0], "script type");
+      return EX_USAGE;
+   }
 
-      if (toolbox_strcmp(argv[optind], "default") == 0) {
-        return Script_GetDefault(apm);
-      } else if (toolbox_strcmp(argv[optind], "current") == 0) {
-        return Script_GetCurrent(apm);
-      } else if (toolbox_strcmp(argv[optind], "set") == 0) {
-        optind++;
-        if (optind < argc) {
-           return Script_Set(apm, argv[optind], quiet_flag);
-        } else {
-           fprintf(stderr, "Missing script path\n");
-           ScriptHelp(argv[0]);
-           return EX_USAGE;
-        }
-      } else if (toolbox_strcmp(argv[optind], "enable") == 0) {
-        return Script_Enable(apm, quiet_flag);
-      } else if (toolbox_strcmp(argv[optind], "disable") == 0) {
-        return Script_Disable(apm, quiet_flag);
-      } else {
-        fprintf(stderr, "Unknown subcommand");
+   apm = argv[optind++];
+
+   if (!Script_CheckName(apm)) {
+      ToolboxUnknownEntityError(argv[0], "script type", apm);
+      return EX_USAGE;
+   }
+
+   if (optind >= argc) {
+      ToolboxMissingEntityError(argv[0], "subcommand");
+      return EX_USAGE;
+   }
+
+   if (toolbox_strcmp(argv[optind], "default") == 0) {
+      return Script_GetDefault(apm);
+   } else if (toolbox_strcmp(argv[optind], "current") == 0) {
+      return Script_GetCurrent(apm);
+   } else if (toolbox_strcmp(argv[optind], "set") == 0) {
+      if (++optind >= argc) {
+         ToolboxMissingEntityError(argv[0], "script path");
+         return EX_USAGE;
       }
+      return Script_Set(apm, argv[optind], quiet_flag);
+   } else if (toolbox_strcmp(argv[optind], "enable") == 0) {
+      return Script_Enable(apm, quiet_flag);
+   } else if (toolbox_strcmp(argv[optind], "disable") == 0) {
+      return Script_Disable(apm, quiet_flag);
+   } else {
+      ToolboxUnknownEntityError(argv[0], "subcommand", argv[optind]);
+      return EX_USAGE;
    }
-   ScriptHelp(argv[0]);
-   return EX_USAGE;
 }
 
 
@@ -574,19 +596,16 @@ static int
 TimeSyncCommand(char **argv, // IN: command line arguments
                 int argc)    // IN: The length of the command line arguments
 {
-   if (CheckArgumentLength(argv, argc)) {
-      if (toolbox_strcmp(argv[optind], "enable") == 0) {
-        return TimeSync_Enable(quiet_flag);
-      } else if (toolbox_strcmp(argv[optind], "disable") == 0) {
-        return TimeSync_Disable(quiet_flag);
-      } else if (toolbox_strcmp(argv[optind], "status") == 0) {
-        return TimeSync_Status();
-      } else {
-        fprintf(stderr, "Unknown subcommand");
-      }
+   if (toolbox_strcmp(argv[optind], "enable") == 0) {
+      return TimeSync_Enable(quiet_flag);
+   } else if (toolbox_strcmp(argv[optind], "disable") == 0) {
+      return TimeSync_Disable(quiet_flag);
+   } else if (toolbox_strcmp(argv[optind], "status") == 0) {
+      return TimeSync_Status();
+   } else {
+      ToolboxUnknownEntityError(argv[0], "subcommand", argv[optind]);
+      return EX_USAGE;
    }
-   TimeSyncHelp(argv[0]);
-   return EX_USAGE;
 }
 
 
@@ -610,20 +629,15 @@ static CmdTable *
 ParseCommand(char **argv, // IN: Command line arguments
              int argc)    // IN: Length of command line arguments
 {
-   if (optind < argc) {
-      int i = 0;
-      while (commands[i].command != 0) {
-        if (toolbox_strcmp(commands[i].command, argv[optind]) == 0) {
-           return &commands[i];
-        }
-        i++;
+   int i;
+
+   for (i = 0; i < ARRAYSIZE(commands); i++) {
+      if (toolbox_strcmp(commands[i].command, argv[optind]) == 0) {
+         return &commands[i];
       }
-      return &commands[i];
-   } else {
-      fprintf(stderr, "Missing command\n");
-      ToolboxCmdHelp(argv[0]);
-      exit(EX_USAGE);
    }
+
+   return NULL;
 }
 
 
@@ -649,7 +663,12 @@ int
 main(int argc,    // IN: length of command line arguments
      char **argv) // IN: Command line arguments
 {
+   Bool show_help = FALSE;
+   Bool show_version = FALSE;
+   CmdTable *cmd = NULL;
    int c;
+   int retval;
+
    /*
     * Check if we are in a VM
     */
@@ -658,11 +677,6 @@ main(int argc,    // IN: length of command line arguments
       exit(EXIT_FAILURE);
    }
 
-   if (argc < 2) {
-      ToolboxCmdHelp(argv[0]);
-      exit(EX_USAGE);
-   }
-
    /*
     * Parse the command line optional arguments
     */
@@ -676,48 +690,65 @@ main(int argc,    // IN: length of command line arguments
 #endif
 
       /* Detect the end of the options. */
-      if (c == -1)
-        break;
+      if (c == -1) {
+         break;
+      }
 
       switch (c) {
       case 'h':
-        ToolboxCmdHelp(argv[0]);
-        exit(EXIT_SUCCESS);
+         show_help = TRUE;
+         break;
 
       case 'v':
-        printf("%s (%s)\n", TOOLBOXCMD_VERSION_STRING, BUILD_NUMBER);
-        exit(EXIT_SUCCESS);
+         show_version = TRUE;
+         break;
 
       case 'q':
-        quiet_flag = 1;
-        break;
+         quiet_flag = TRUE;
+         break;
 
       case '?':
-        /* getopt_long already printed an error message. */
-        ToolboxCmdHelp(argv[0]);
-        abort();
-        break;
+         /* getopt_long already printed an error message. */
+         fprintf(stderr, "Try '%s -h' for more information.\n", argv[0]);
+         return EXIT_FAILURE;
 
       default:
-        abort();
+         return EXIT_FAILURE;
       }
    }
 
-   /* Process any remaining command line arguments (not options), and
-    * execute corresponding command
-    */
-   if (optind < argc) {
-      CmdTable *cmd = ParseCommand(argv, argc);
-      if (cmd->command == NULL) {
-         ToolboxCmdHelp(argv[0]);
-        return EX_USAGE;
+   if (show_version) {
+      printf("%s (%s)\n", TOOLBOXCMD_VERSION_STRING, BUILD_NUMBER);
+   } else if (show_help) {
+      ToolboxCmdHelp(argv[0]);
+   } else {
+      /* Process any remaining command line arguments (not options), and
+       * execute corresponding command
+       */
+      if (optind >= argc) {
+         ToolboxMissingEntityError(argv[0], "command");
+         retval = EX_USAGE;
+      } else if ((cmd = ParseCommand(argv, argc)) == NULL) {
+         ToolboxUnknownEntityError(argv[0], "command", argv[optind]);
+         retval = EX_USAGE;
+      } else if (cmd->requireRoot && !System_IsUserAdmin()) {
+         fprintf(stderr, "%s: You must be root to perform %s operations",
+                 argv[0], cmd->command);
+         retval = EX_NOPERM;
+      } else if (cmd->requireArguments && ++optind >= argc) {
+         ToolboxMissingEntityError(argv[0], "subcommand");
+         retval = EX_USAGE;
+      } else {
+         retval = cmd->func(argv, argc);
       }
-      if (cmd->requireRoot && !System_IsUserAdmin()) {
-        fprintf(stderr,"You must be root to perform %s operations\n",
-                 cmd->command);
-        return EX_NOPERM;
+
+      if (retval == EX_USAGE && (cmd == NULL || strcmp(cmd->command, "help"))) {
+         fprintf(stderr, "Try '%s help%s%s' for more information.\n",
+                 argv[0], cmd ? " " : "", cmd ? cmd->command : "");
       }
-      return cmd->func(argv, argc);
+
+      return retval;
    }
+
    return EXIT_SUCCESS;
 }
index d860bad9c03402a386023ee427ebaaf88e52e6e3..901f2e5f2db84757f9e5f4e3ea067edf9db681f1 100644 (file)
@@ -94,12 +94,12 @@ int TimeSync_Status(void);
  * Script Operations
  */
 
-int Script_GetDefault(char*);
-int Script_GetCurrent(char*);
-int Script_Enable(char*, int);
-int Script_Disable(char*, int);
-int Script_Set(char*, char*, int);
-
+int Script_GetDefault(const char *);
+int Script_GetCurrent(const char *);
+int Script_Enable(const char *, int);
+int Script_Disable(const char *, int);
+int Script_Set(const char *, const char *, int);
+Bool Script_CheckName(const char *);
 
 /*
  * Disk Shrink Operations
index 80030db37171e72c71912ff2b7fa0b79fce82033..ccf8bf01543264751d15b694088cfc74c9f7eb99 100644 (file)
@@ -43,9 +43,9 @@ typedef enum ScriptType {
    Current
 } ScriptType;
 
-static int ScriptToggle(char *apm, Bool enable, int quiet_flag);
-static char* GetConfName(char *apm);
-static int GetConfEntry(char *apm, ScriptType type);
+static int ScriptToggle(const char *apm, Bool enable, int quiet_flag);
+static const char* GetConfName(const char *apm);
+static int GetConfEntry(const char *apm, ScriptType type);
 
 
 /*
@@ -64,8 +64,8 @@ static int GetConfEntry(char *apm, ScriptType type);
  *-----------------------------------------------------------------------------
  */
 
-static char *
-GetConfName(char *apm) // IN: apm name.
+static const char *
+GetConfName(const char *apm) // IN: apm name.
 {
    if (toolbox_strcmp(apm, SCRIPT_SUSPEND) == 0) {
       return CONFNAME_SUSPENDSCRIPT;
@@ -135,12 +135,12 @@ LoadConfFile(void)
  */
 
 static int
-GetConfEntry(char *apm,        // IN: apm name
+GetConfEntry(const char *apm,  // IN: apm name
              ScriptType type)  // IN: Script type (default or current)
 {
    gchar *entry = NULL;
    GKeyFile *confDict = NULL;
-   char *confName;
+   const char *confName;
    int ret;
 
    confName = GetConfName(apm);
@@ -193,7 +193,7 @@ GetConfEntry(char *apm,        // IN: apm name
  */
 
 int
-Script_GetDefault(char *apm) // IN: APM name
+Script_GetDefault(const char *apm) // IN: APM name
 {
    return GetConfEntry(apm, Default);
 }
@@ -218,7 +218,7 @@ Script_GetDefault(char *apm) // IN: APM name
  */
 
 int
-Script_GetCurrent(char *apm) // IN: apm function name
+Script_GetCurrent(const char *apm) // IN: apm function name
 {
    return GetConfEntry(apm, Current);
 }
@@ -244,12 +244,12 @@ Script_GetCurrent(char *apm) // IN: apm function name
  */
 
 static int
-ScriptToggle(char *apm,       // IN: APM name
-              Bool enable,    // IN: status
-              int quiet_flag) // IN: Verbosity flag
+ScriptToggle(const char *apm, // IN: APM name
+             Bool enable,     // IN: status
+             int quiet_flag)  // IN: Verbosity flag
 {
    const char *path;
-   char *confName;
+   const char *confName;
    gchar *confPath;
    int ret = EXIT_SUCCESS;
    GKeyFile *confDict;
@@ -301,8 +301,8 @@ ScriptToggle(char *apm,       // IN: APM name
  */
 
 int
-Script_Enable(char *apm,      // IN: APM name
-              int quiet_flag) // IN: Verbosity flag
+Script_Enable(const char *apm,   // IN: APM name
+              int quiet_flag)    // IN: Verbosity flag
 {
    return ScriptToggle(apm, TRUE, quiet_flag);
 }
@@ -325,8 +325,8 @@ Script_Enable(char *apm,      // IN: APM name
  */
 
 int
-Script_Disable(char *apm,      // IN: APM name
-               int quiet_flag) // IN: Verbosity Flag
+Script_Disable(const char *apm,  // IN: APM name
+               int quiet_flag)   // IN: Verbosity Flag
 {
    return ScriptToggle(apm, FALSE, quiet_flag);
 }
@@ -352,11 +352,11 @@ Script_Disable(char *apm,      // IN: APM name
  */
 
 int
-Script_Set(char *apm,     // IN: APM name
-           char *path,    // IN: path to script
-           int quiet_flag) // IN: Verbosity flag
+Script_Set(const char *apm,   // IN: APM name
+           const char *path,  // IN: path to script
+           int quiet_flag)    // IN: Verbosity flag
 {
-   char *confName;
+   const char *confName;
    int ret = EXIT_SUCCESS;
    gchar *confPath = NULL;
    GKeyFile *confDict = NULL;
@@ -389,3 +389,25 @@ Script_Set(char *apm,         // IN: APM name
    return ret;
 }
 
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Script_CheckName  --
+ *
+ *      Check if it is known script
+ *
+ * Results:
+ *      TRUE if name is known, FALSE otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+Script_CheckName(const char *apm) // IN: script name
+{
+   return GetConfName(apm) != NULL;
+}
index e9fa559cbc5db37893672a9276c15277f68b46cc..201b6e4b3fdf0d87405561ebb96146440795ac4c 100644 (file)
@@ -1821,6 +1821,7 @@ CopyPaste_GetVmxCopyPasteVersion(void)
    char *reply = NULL;
    size_t replyLen;
 
+   Debug("%s: enter\n", __FUNCTION__);
    if (!RpcOut_sendOne(&reply, &replyLen, "vmx.capability.copypaste_version")) {
       Debug("CopyPaste_GetVmxCopyPasteVersion: could not get VMX copyPaste "
             "version capability: %s\n", reply ? reply : "NULL");
@@ -1857,6 +1858,7 @@ CopyPaste_GetVmxCopyPasteVersion(void)
 Bool
 CopyPaste_RegisterCapability(void)
 {
+   Debug("%s: enter\n", __FUNCTION__);
    /* Tell the VMX about the copyPaste version we support. */
    if (!RpcOut_sendOne(NULL, NULL, "tools.capability.copypaste_version 2")) {
       Debug("CopyPaste_RegisterCapability: could not set guest copypaste "
@@ -1888,6 +1890,7 @@ CopyPaste_RegisterCapability(void)
 Bool
 CopyPaste_Register(GtkWidget* mainWnd)
 {
+   Debug("%s: enter\n", __FUNCTION__);
    /* Text copy/paste initialization for all versions. */
 #ifndef GDK_SELECTION_CLIPBOARD
    GDK_SELECTION_CLIPBOARD = gdk_atom_intern("CLIPBOARD", FALSE);
@@ -1963,6 +1966,7 @@ CopyPaste_Register(GtkWidget* mainWnd)
 void
 CopyPaste_Unregister(GtkWidget* mainWnd)
 {
+   Debug("%s: enter\n", __FUNCTION__);
    gtk_signal_disconnect_by_func(GTK_OBJECT(mainWnd),
                                  GTK_SIGNAL_FUNC(CopyPasteSelectionReceivedCB),
                                  mainWnd);
@@ -1972,6 +1976,11 @@ CopyPaste_Unregister(GtkWidget* mainWnd)
    gtk_signal_disconnect_by_func(GTK_OBJECT(mainWnd),
                                  GTK_SIGNAL_FUNC(CopyPasteSelectionClearCB),
                                  mainWnd);
+   RpcIn_UnregisterCallback(gRpcIn, "copypaste.hg.data.set");
+   RpcIn_UnregisterCallback(gRpcIn, "copypaste.hg.data.finish");
+   RpcIn_UnregisterCallback(gRpcIn, "copypaste.gh.data.get");
+   RpcIn_UnregisterCallback(gRpcIn, "copypaste.gh.get.next.file");
+   RpcIn_UnregisterCallback(gRpcIn, "copypaste.gh.finish");
 }
 
 
@@ -1994,6 +2003,7 @@ CopyPaste_Unregister(GtkWidget* mainWnd)
 void
 CopyPaste_OnReset(void)
 {
+   Debug("%s: enter\n", __FUNCTION__);
    if (gHGFCPFileTransferStatus == FCP_FILE_TRANSFERRING) {
       File_DeleteDirectoryTree(gFileRoot);
       if (DnD_BlockIsReady(&gBlockCtrl) &&
@@ -2073,6 +2083,7 @@ CopyPaste_IsRpcCPSupported(void)
 void
 CopyPasteStateInit(void)
 {
+   Debug("%s: enter\n", __FUNCTION__);
    gHostClipboardBuf[0] = '\0';
    gGuestSelPrimaryBuf[0] = '\0';
    gGuestSelClipboardBuf[0] = '\0';
@@ -2087,6 +2098,6 @@ CopyPasteStateInit(void)
        * or greater.
        */
       gFileRootSize = DnD_GetNewFileRoot(gFileRoot, sizeof gFileRoot);
-      Debug("CopyPaste_Register create file root [%s]\n", gFileRoot);
+      Debug("%s: create file root [%s]\n", __FUNCTION__, gFileRoot);
    }
 }
index 24ac9194f712b3b085e250866e281eec2a25c61a..c5bfe332147e5bf50363c59cafda885a5b9e67f4 100644 (file)
@@ -181,17 +181,21 @@ CopyPasteDnDWrapper::RegisterCP()
          Debug("%s: Setting block control to %p (fd %d)\n",
                __func__, m_blockCtrl, m_blockCtrl->fd);
          m_copyPasteUI->SetBlockControl(m_blockCtrl);
-         m_copyPasteUI->Init();
-         SetCPIsRegistered(TRUE);
-         int version = GetCPVersion();
-         Debug("%s: version is %d\n", __FUNCTION__, version);
-         if (version >= 3) {
-            m_copyPasteUI->VmxCopyPasteVersionChanged(gRpcIn, version);
-            m_copyPasteUI->SetCopyPasteAllowed(TRUE);
-            m_isLegacy = false;
+         if (m_copyPasteUI->Init()) {
+            SetCPIsRegistered(TRUE);
+            int version = GetCPVersion();
+            Debug("%s: version is %d\n", __FUNCTION__, version);
+            if (version >= 3) {
+               m_copyPasteUI->VmxCopyPasteVersionChanged(gRpcIn, version);
+               m_copyPasteUI->SetCopyPasteAllowed(TRUE);
+               m_isLegacy = false;
+            } else {
+               Debug("%s: version < 3, unregistering.\n", __FUNCTION__);
+               UnregisterCP();
+            }
          } else {
-            Debug("%s: version < 3, unregistering.\n", __FUNCTION__);
-            UnregisterCP();
+            delete m_copyPasteUI;
+            m_copyPasteUI = NULL;
          }
       }
    }
@@ -240,25 +244,28 @@ CopyPasteDnDWrapper::RegisterDnD()
                __func__, m_blockCtrl, m_blockCtrl->fd);
          m_dndUI->SetBlockControl(m_blockCtrl);
 
-         m_dndUI->Init();
-
-         UnityDnD state;
-         state.detWnd = m_dndUI->GetDetWndAsWidget(true);
-         state.setMode = CopyPasteDnDWrapper_SetUnityMode;
-         Unity_SetActiveDnDDetWnd(&state);
-
-         SetDnDIsRegistered(TRUE);
-         int version = GetDnDVersion();
-         Debug("%s: dnd version is %d\n", __FUNCTION__, version);
-         if (version >= 3) {
-            Debug("%s: calling VmxDnDVersionChanged (version %d) and SetDnDAllowed\n",
-               __FUNCTION__, version);
-            m_dndUI->VmxDnDVersionChanged(gRpcIn, version);
-            m_dndUI->SetDnDAllowed(TRUE);
-            m_isLegacy = false;
+         if (m_dndUI->Init()) {
+            UnityDnD state;
+            state.detWnd = m_dndUI->GetDetWndAsWidget();
+            state.setMode = CopyPasteDnDWrapper_SetUnityMode;
+            Unity_SetActiveDnDDetWnd(&state);
+
+            SetDnDIsRegistered(TRUE);
+            int version = GetDnDVersion();
+            Debug("%s: dnd version is %d\n", __FUNCTION__, version);
+            if (version >= 3) {
+               Debug("%s: calling VmxDnDVersionChanged (version %d) and SetDnDAllowed\n",
+                     __FUNCTION__, version);
+               m_dndUI->VmxDnDVersionChanged(gRpcIn, version);
+               m_dndUI->SetDnDAllowed(TRUE);
+               m_isLegacy = false;
+            } else {
+               Debug("%s: version < 3, unregistering.\n", __FUNCTION__);
+               UnregisterDnD();
+            }
          } else {
-            Debug("%s: version < 3, unregistering.\n", __FUNCTION__);
-            UnregisterDnD();
+            delete m_dndUI;
+            m_dndUI = NULL;
          }
       }
    }
@@ -450,10 +457,22 @@ CopyPasteDnDWrapper::OnReset()
    if (IsCPRegistered()) {
       UnregisterCP();
    }
-   RegisterCP();
-   RegisterDnD();
+   if (!IsCPRegistered()) {
+      RegisterCP();
+   }
+   if (!IsDnDRegistered()) {
+      RegisterDnD();
+   }
    if (!IsDnDRegistered() || !IsCPRegistered()) {
       Debug("%s: unable to reset fully!\n", __FUNCTION__);
    }
+   if (m_isLegacy) {
+      if (IsCPRegistered()) {
+         CopyPaste_OnReset();
+      }
+      if (IsDnDRegistered()) {
+         DnD_OnReset(m_hgWnd, m_ghWnd);
+      }
+   }
 }
 
index cd6223496f35209fcb4e8969ddf233d47570f67b..16d6ec4d9cef8c5cedc3df5a049d055297837eec 100644 (file)
@@ -66,8 +66,6 @@ CopyPasteUI::CopyPasteUI()
  : mClipboardEmpty(true),
    mHGStagingDir(""),
    mIsClipboardOwner(false),
-   mClipTimePrev(0),
-   mPrimTimePrev(0),
    mHGGetFilesInitiated(false),
    mFileTransferDone(false),
    mBlockAdded(false),
@@ -94,14 +92,13 @@ CopyPasteUI::CopyPasteUI()
  *-----------------------------------------------------------------------------
  */
 
-void
+bool
 CopyPasteUI::Init()
 {
    if (mInited) {
-      return;
+      return true;
    }
 
-   mInited = true;
    CPClipboard_Init(&mClipboard);
 
    Gtk::TargetEntry gnome(FCP_TARGET_NAME_GNOME_COPIED_FILES);
@@ -116,7 +113,7 @@ CopyPasteUI::Init()
    if (!RpcOut_sendOne(NULL, NULL, "tools.capability.copypaste_version 3")) {
       Debug("%s: could not set guest copypaste version capability\n",
             __FUNCTION__);
-      return;
+      return false;
    }
    Debug("%s: set copypaste version 3\n", __FUNCTION__);
 
@@ -126,6 +123,8 @@ CopyPasteUI::Init()
       sigc::mem_fun(this, &CopyPasteUI::GetLocalClipboard));
    mCP.localGetFilesDoneChanged.connect(
       sigc::mem_fun(this, &CopyPasteUI::GetLocalFilesDone));
+   mInited = true;
+   return true;
 }
 
 
@@ -580,64 +579,31 @@ CopyPasteUI::LocalPrimTimestampCB(const Gtk::SelectionData& sd)  // IN
    mGHSelection = GDK_SELECTION_PRIMARY;
    if (mClipTime > mPrimTime) {
       mGHSelection = GDK_SELECTION_CLIPBOARD;
-      Debug("%s: mClipTimePrev: %"FMT64"u.", __FUNCTION__, mClipTimePrev);
-   } else {
-      Debug("%s: mPrimTimePrev: %"FMT64"u.", __FUNCTION__, mPrimTimePrev);
    }
 
-   mPrimTimePrev = mPrimTime;
-   mClipTimePrev = mClipTime;
-
-   /* Ask for available targets from active selection. */
-   Glib::RefPtr<Gtk::Clipboard> refClipboard =
-      Gtk::Clipboard::get(mGHSelection);
+   Glib::RefPtr<Gtk::Clipboard> refClipboard;
+again:
+   refClipboard = Gtk::Clipboard::get(mGHSelection);
 
-   refClipboard->request_targets(
-      sigc::mem_fun(this, &CopyPasteUI::LocalReceivedTargetsCB));
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * CopyPasteUI::LocalReceivedTargetsCB --
- *
- *      Received targets. Check if any desired target available. If so,
- *      ask for all supported contents.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      Clipboard owner may send us file list.
- *
- *----------------------------------------------------------------------
- */
-
-void
-CopyPasteUI::LocalReceivedTargetsCB(const Glib::StringArrayHandle& targetsArray)  // IN
-{
-   std::list<utf::string> targets = targetsArray;
-   Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get(mGHSelection);
+   Debug("%s: trying %s selection, trying again\n",
+          __FUNCTION__,
+          mGHSelection == GDK_SELECTION_PRIMARY ? "Primary" : "Clip");
 
-   Debug("%s: enter", __FUNCTION__);
    CPClipboard_Clear(&mClipboard);
 
-   if (std::find(targets.begin(),
-                 targets.end(),
-                 FCP_TARGET_NAME_GNOME_COPIED_FILES) != targets.end()) {
-      Debug("%s: gnome copy file list available\n", __FUNCTION__);
-      refClipboard->request_contents(FCP_TARGET_NAME_GNOME_COPIED_FILES,
-                                     sigc::mem_fun(this,
-                                                   &CopyPasteUI::LocalReceivedFileListCB));
-      return;
+   /* First check for URIs. This must always be done first */
+   bool haveURIs = false;
+   std::string format;
+   if (refClipboard->wait_is_target_available(FCP_TARGET_NAME_GNOME_COPIED_FILES)) {
+      format = FCP_TARGET_NAME_GNOME_COPIED_FILES;
+      haveURIs = true;
+   } else if (refClipboard->wait_is_target_available(FCP_TARGET_NAME_URI_LIST)) {
+      format = FCP_TARGET_NAME_URI_LIST;
+      haveURIs = true;
    }
 
-   if (std::find(targets.begin(),
-                 targets.end(),
-                 FCP_TARGET_NAME_URI_LIST) != targets.end()) {
-      Debug("%s: KDE copy file list available\n", __FUNCTION__);
-      refClipboard->request_contents(FCP_TARGET_NAME_URI_LIST,
+   if (haveURIs) {
+      refClipboard->request_contents(format,
                                      sigc::mem_fun(this,
                                                    &CopyPasteUI::LocalReceivedFileListCB));
       return;
@@ -645,13 +611,13 @@ CopyPasteUI::LocalReceivedTargetsCB(const Glib::StringArrayHandle& targetsArray)
 
    /* Try to get image data from clipboard. */
    Glib::RefPtr<Gdk::Pixbuf> img = refClipboard->wait_for_image();
+   gsize bufSize;
    if (img) {
       gchar *buf = NULL;
-      gsize bufSize;
 
       img->save_to_buffer(buf, bufSize, Glib::ustring("png"));
       if (bufSize > 0  &&
-          bufSize <= (int)DNDMSG_MAX_ARGSZ &&
+          bufSize <= (int)CPCLIPITEM_MAX_SIZE_V3 &&
           CPClipboard_SetItem(&mClipboard, CPFORMAT_IMG_PNG,
                               buf, bufSize)) {
          mCP.SetRemoteClipboard(&mClipboard);
@@ -663,33 +629,71 @@ CopyPasteUI::LocalReceivedTargetsCB(const Glib::StringArrayHandle& targetsArray)
       return;
    }
 
-   /*
-    * Try to get RTF data from local clipboard. 2 targets are supported, and
-    * both share same callback because data is same.
-    */
-   if (std::find(targets.begin(),
-                 targets.end(),
-                 TARGET_NAME_APPLICATION_RTF) != targets.end()) {
-      Debug("%s: TARGET_NAME_APPLICATION_RTF available\n", __FUNCTION__);
-      refClipboard->request_contents(TARGET_NAME_APPLICATION_RTF,
-                                     sigc::mem_fun(this,
-                                                   &CopyPasteUI::LocalReceivedRTFCB));
-      return;
+   /* Try to get RTF data from clipboard. */
+   bool haveRTF = false;
+   if (refClipboard->wait_is_target_available(TARGET_NAME_APPLICATION_RTF)) {
+      Debug("%s: RTF is available\n", __FUNCTION__);
+      format = TARGET_NAME_APPLICATION_RTF;
+      haveRTF = true;
+   }
+   if (refClipboard->wait_is_target_available(TARGET_NAME_TEXT_RICHTEXT)) {
+      Debug("%s: RICHTEXT is available\n", __FUNCTION__);
+      format = TARGET_NAME_TEXT_RICHTEXT;
+      haveRTF = true;
    }
 
-   if (std::find(targets.begin(),
-                 targets.end(),
-                 TARGET_NAME_TEXT_RICHTEXT) != targets.end()) {
-      Debug("%s: TARGET_NAME_TEXT_RICHTEXT available\n", __FUNCTION__);
-      refClipboard->request_contents(TARGET_NAME_TEXT_RICHTEXT,
-                                     sigc::mem_fun(this,
-                                                   &CopyPasteUI::LocalReceivedRTFCB));
-      return;
+   if (haveRTF) {
+      /*
+       * There is a function for waiting for rtf data, but that was leading
+       * to crashes. It's use required we instantiate a class that implements
+       * Gtk::TextBuffer and then query that class for a reference to it's
+       * TextBuffer instance. This all compiled fine but crashed in testing
+       * so we opt to use the more generic API here which seemed more stable.
+       */
+      Gtk::SelectionData sdata = refClipboard->wait_for_contents(format);
+      bufSize = sdata.get_length();
+      if (bufSize > 0  &&
+          bufSize <= (int)CPCLIPITEM_MAX_SIZE_V3 &&
+          CPClipboard_SetItem(&mClipboard, CPFORMAT_RTF,
+                              (const void *)sdata.get_data(), bufSize + 1)) {
+         mCP.SetRemoteClipboard(&mClipboard);
+         Debug("%s: Got RTF\n", __FUNCTION__);
+         return;
+      } else {
+         Debug("%s: Failed to get RTF size %d max %d\n",
+               __FUNCTION__, (int) bufSize, (int)CPCLIPITEM_MAX_SIZE_V3);
+      }
    }
 
-   Debug("%s: ask for text\n", __FUNCTION__);
-   refClipboard->request_text(sigc::mem_fun(this,
-                                            &CopyPasteUI::LocalReceivedTextCB));
+   /* Try to get Text data from clipboard. */
+   if (refClipboard->wait_is_text_available()) {
+      Debug("%s: ask for text\n", __FUNCTION__);
+      Glib::ustring str = refClipboard->wait_for_text();
+      bufSize = str.size();
+      if (bufSize > 0  &&
+          bufSize <= (int)CPCLIPITEM_MAX_SIZE_V3 &&
+          CPClipboard_SetItem(&mClipboard, CPFORMAT_TEXT,
+                              (const void *)str.data(), bufSize + 1)) {
+         mCP.SetRemoteClipboard(&mClipboard);
+         Debug("%s: Got TEXT: %"FMTSZ"u\n", __FUNCTION__, bufSize);
+         return;
+      } else if (mClipTime == mPrimTime && mClipTime) {
+         /*
+          * With 'cut' operation OpenOffice will put data into clipboard but
+          * set the same timestamp for both clipboard and primary selection.
+          * If primary timestamp is same as clipboard timestamp, we should try
+          * clipboard again if primary selection is empty. For details, please
+          * refer to bug 300780.
+          */
+         mClipTime = 0;
+         mPrimTime = 0;
+         mGHSelection = GDK_SELECTION_CLIPBOARD;
+         Debug("%s: trying again with clip\n", __FUNCTION__);
+         goto again;
+      } else {
+         Debug("%s: Failed to get TEXT\n", __FUNCTION__);
+      }
+   }
 }
 
 
@@ -724,113 +728,6 @@ CopyPasteUI::LocalReceivedFileListCB(const Gtk::SelectionData& sd)        // IN
 }
 
 
-/*
- *----------------------------------------------------------------------
- *
- * CopyPasteUI::LocalReceivedRTFCB --
- *
- *      Got clipboard (or primary selection) RTF text, add to local
- *      clipboard cache and send clipboard to host.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-CopyPasteUI::LocalReceivedRTFCB(const Gtk::SelectionData& sd) // IN
-{
-   utf::string source = sd.get_data_as_string().c_str();
-   Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get(mGHSelection);
-
-   /* Add NUL terminator. */
-   if (source.bytes() > 0 &&
-       source.bytes() < DNDMSG_MAX_ARGSZ &&
-       CPClipboard_SetItem(&mClipboard, CPFORMAT_RTF, source.c_str(),
-                           source.bytes() + 1)) {
-      Debug("%s: Got RTF, size %"FMTSZ"u\n", __FUNCTION__, source.bytes());
-   } else {
-      Debug("%s: Failed to get RTF\n", __FUNCTION__);
-   }
-
-   /*
-    * Still should try to get plain text. LocalReceivedTextCB will send data
-    * to guest.
-    */
-   Debug("%s: ask for text\n", __FUNCTION__);
-   refClipboard->request_text(sigc::mem_fun(this,
-                                            &CopyPasteUI::LocalReceivedTextCB));
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * CopyPasteUI::LocalReceivedTextCB --
- *
- *      Got clipboard (or primary selection) text, add to local clipboard
- *      cache and send clipboard to host.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-CopyPasteUI::LocalReceivedTextCB(const Glib::ustring& text)        // IN
-{
-   Debug("%s: enter", __FUNCTION__);
-   utf::string source = text;
-
-   /*
-    * With 'cut' operation OpenOffice will put data into clipboard but
-    * set same timestamp for both clipboard and primary selection.
-    * If primary timestamp is same as clipboard timestamp, we should try
-    * clipboard again if primary selection is empty. For details please
-    * refer to bug 300780.
-    */
-   if (0 == source.bytes() &&
-       mClipTime == mPrimTime &&
-       mClipTime != 0) {
-      mClipTime = 0;
-      mPrimTime = 0;
-      mGHSelection = GDK_SELECTION_CLIPBOARD;
-
-      /* Ask for available targets from active selection. */
-      Glib::RefPtr<Gtk::Clipboard> refClipboard =
-         Gtk::Clipboard::get(mGHSelection);
-
-      refClipboard->request_targets(
-         sigc::mem_fun(this, &CopyPasteUI::LocalReceivedTargetsCB));
-      return;
-   }
-
-   Debug("%s: Got text: %s", __FUNCTION__, source.c_str());
-
-   /* Add NUL terminator. */
-   if (source.bytes() > 0 &&
-       source.bytes() < CPCLIPITEM_MAX_SIZE_V3 &&
-       CPClipboard_SetItem(&mClipboard, CPFORMAT_TEXT, source.c_str(),
-                           source.bytes() + 1)) {
-      Debug("%s: got text, size %"FMTSZ"u\n", __FUNCTION__,  source.bytes());
-   } else {
-      Debug("%s: failed to get text\n", __FUNCTION__);
-   }
-
-   if (!CPClipboard_IsEmpty(&mClipboard)) {
-      mCP.SetRemoteClipboard(&mClipboard);
-   }
-}
-
-
 /*
  *-----------------------------------------------------------------------------
  *
index c77cd0a667f5b36adee19acfcb997557006a16da..66d856a5b1c42a3ec644cddcba9240e678f8894c 100644 (file)
@@ -54,7 +54,7 @@ class CopyPasteUI : public sigc::trackable
 public:
    CopyPasteUI();
    virtual ~CopyPasteUI();
-   void Init();
+   bool Init();
    void VmxCopyPasteVersionChanged(struct RpcIn *rpcIn,
                                    uint32 version);
    void SetCopyPasteAllowed(bool isCopyPasteAllowed)
@@ -79,10 +79,7 @@ private:
    bool GetLocalClipboard(CPClipboard *clip);
    void LocalClipboardTimestampCB(const Gtk::SelectionData& sd);
    void LocalPrimTimestampCB(const Gtk::SelectionData& sd);
-   void LocalReceivedTargetsCB(const Glib::StringArrayHandle& targets_array);
    void LocalReceivedFileListCB(const Gtk::SelectionData& selection_data);
-   void LocalReceivedRTFCB(const Gtk::SelectionData& selection_data);
-   void LocalReceivedTextCB(const Glib::ustring& text);
    void GetLocalFilesDone(bool success);
 
    /* Conversion methods. */
@@ -100,8 +97,6 @@ private:
    bool mIsClipboardOwner;
    uint64 mClipTime;
    uint64 mPrimTime;
-   uint64 mClipTimePrev;
-   uint64 mPrimTimePrev;
    GdkAtom mGHSelection;
    CPClipboard mClipboard;
 
index 68bf9f6ba52ebf44c8bb324f312d55547bca507d..9a5f3aa95cf9e6bda1c5bbe873ed81792820470a 100644 (file)
@@ -2591,6 +2591,17 @@ DnD_Unregister(GtkWidget *hgWnd,        // IN: The widget for hg dnd
    gtk_signal_disconnect_by_func(GTK_OBJECT(ghWnd),
                                  GTK_SIGNAL_FUNC(DnDGtkDragDropCB),
                                  ghWnd);
+
+   RpcIn_UnregisterCallback(gRpcIn, "dnd.data.set");
+   RpcIn_UnregisterCallback(gRpcIn, "dnd.enter");
+   RpcIn_UnregisterCallback(gRpcIn, "dnd.move");
+   RpcIn_UnregisterCallback(gRpcIn, "dnd.drop");
+   RpcIn_UnregisterCallback(gRpcIn, "dnd.data.finish");
+
+   /* Guest->Host RPC callbacks */
+   RpcIn_UnregisterCallback(gRpcIn, "dnd.ungrab");
+   RpcIn_UnregisterCallback(gRpcIn, "dnd.data.get.file");
+   RpcIn_UnregisterCallback(gRpcIn, "dnd.finish");
 }
 
 
index 82691d4c09e99f7f32dd075d52a601b4f1faa301..f94224b2c0050569dbcb3a93adc10bd485d6ef63 100644 (file)
@@ -36,6 +36,7 @@ extern "C" {
 #include "cpName.h"
 #include "debug.h"
 #include "cpNameUtil.h"
+#include "hostinfo.h"
 #include "rpcout.h"
 #include "eventManager.h"
 #include "unity.h"
@@ -55,20 +56,19 @@ DnDUI::DnDUI(DblLnkLst_Links *eventQueue)
     : m_eventQueue(eventQueue),
       m_DnD(NULL),
       m_detWnd(NULL),
-      m_detWndFull(NULL),
       m_blockCtrl(NULL),
       m_HGGetDataInProgress(false),
       m_blockAdded(false),
       m_GHDnDInProgress(false),
-      m_GHDnDHostStatus(false),
-      m_GHDnDAction((Gdk::DragAction)0),
       m_GHDnDDataReceived(false),
-      m_GHDnDDropOccurred(false),
-      m_VMIsSource(false),
       m_unityMode(false),
       m_inHGDrag(false),
-      m_effect(DROP_UNKNOWN),
-      m_isFileDnD(false)
+      m_effect(DROP_NONE),
+      m_isFileDnD(false),
+      m_mousePosX(0),
+      m_mousePosY(0),
+      m_dc(NULL),
+      m_destDropTime(0)
 {
    Debug("%s: enter\n", __FUNCTION__);
 }
@@ -82,17 +82,12 @@ DnDUI::DnDUI(DblLnkLst_Links *eventQueue)
 DnDUI::~DnDUI()
 {
    Debug("%s: enter\n", __FUNCTION__);
-   Reset();
    if (m_DnD) {
       delete m_DnD;
    }
    if (m_detWnd) {
       delete m_detWnd;
    }
-   if (m_detWndFull) {
-      delete m_detWndFull;
-   }
-   m_feedbackChanged.disconnect();
    CPClipboard_Destroy(&m_clipboard);
 }
 
@@ -102,12 +97,13 @@ DnDUI::~DnDUI()
  * Initialize DnDUI object.
  */
 
-void
+bool
 DnDUI::Init()
 {
    Debug("%s: enter\n", __FUNCTION__);
    char *reply = NULL;
    size_t replyLen;
+   bool ret = true;
 
    ASSERT(m_eventQueue);
    CPClipboard_Init(&m_clipboard);
@@ -121,11 +117,6 @@ DnDUI::Init()
       Debug("%s: unable to allocate DragDetWnd object\n", __FUNCTION__);
       goto fail;
    }
-   m_detWndFull = new DragDetWnd();
-   if (!m_detWndFull) {
-      Debug("%s: unable to allocate DragDetWnd object\n", __FUNCTION__);
-      goto fail;
-   }
 
 #if defined(DETWNDDEBUG)
 
@@ -137,7 +128,6 @@ DnDUI::Init()
     */
 
    m_detWnd->SetAttributes();
-   m_detWndFull->SetAttributes();
 #endif
 
    SetTargetsAndCallbacks();
@@ -159,56 +149,61 @@ DnDUI::Init()
 
    Debug("%s: VMX version ok: %d\n", __FUNCTION__, atoi(reply));
 
-   m_DnD->reset.connect(sigc::mem_fun(this, &DnDUI::ResetUIStateCB));
+   /* Set common layer callbacks. */
    m_DnD->dragStartChanged.connect(
-      sigc::mem_fun(this, &DnDUI::RemoteDragStartCB));
+      sigc::mem_fun(this, &DnDUI::CommonDragStartCB));
    m_DnD->fileCopyDoneChanged.connect(
-      sigc::mem_fun(this, &DnDUI::GetLocalFilesDoneCB));
+      sigc::mem_fun(this, &DnDUI::CommonSourceFileCopyDoneCB));
    m_DnD->updateDetWndChanged.connect(
-      sigc::mem_fun(this, &DnDUI::UpdateDetWndCB));
+      sigc::mem_fun(this, &DnDUI::CommonUpdateDetWndCB));
    m_DnD->updateUnityDetWndChanged.connect(
-      sigc::mem_fun(this, &DnDUI::UpdateUnityDetWndCB));
+      sigc::mem_fun(this, &DnDUI::CommonUpdateUnityDetWndCB));
+   m_DnD->moveDetWndToMousePos.connect(
+      sigc::mem_fun(this, &DnDUI::CommonMoveDetWndToMousePos));
    m_DnD->sourceCancelChanged.connect(
-      sigc::mem_fun(this, &DnDUI::SourceCancelCB));
+      sigc::mem_fun(this, &DnDUI::CommonSourceCancelCB));
+   m_DnD->targetPrivateDropChanged.connect(
+      sigc::mem_fun(this, &DnDUI::CommonDestPrivateDropCB));
    m_DnD->ghCancel.connect(
-      sigc::mem_fun(this, &DnDUI::GHCancelCB));
+      sigc::mem_fun(this, &DnDUI::CommonDestCancelCB));
    m_DnD->sourceDropChanged.connect(
-      sigc::mem_fun(this, &DnDUI::SourceDropCB));
+      sigc::mem_fun(this, &DnDUI::CommonSourceDropCB));
+   m_DnD->updateMouseChanged.connect(
+      sigc::mem_fun(this, &DnDUI::CommonUpdateMouseCB));
 
+   /* Set Gtk+ callbacks for source. */
+   m_detWnd->signal_drag_begin().connect(
+      sigc::mem_fun(this, &DnDUI::GtkSourceDragBeginCB));
    m_detWnd->signal_drag_data_get().connect(
-      sigc::mem_fun(this, &DnDUI::LocalDragDataGetCB));
+      sigc::mem_fun(this, &DnDUI::GtkSourceDragDataGetCB));
    m_detWnd->signal_drag_end().connect(
-      sigc::mem_fun(this, &DnDUI::LocalDragEndCB));
-   m_detWnd->signal_drag_drop().connect(
-      sigc::mem_fun(this, &DnDUI::LocalDragDropCB));
-   m_detWnd->signal_drag_begin().connect(
-      sigc::mem_fun(this, &DnDUI::LocalDragBeginCB));
+      sigc::mem_fun(this, &DnDUI::GtkSourceDragEndCB));
 
-   UpdateDetWndCB(false, 0, 0);
-   UpdateUnityDetWndCB(false, 0);
+   CommonUpdateDetWndCB(false, 0, 0);
+   CommonUpdateUnityDetWndCB(false, 0, false);
    goto out;
 fail:
+   ret = false;
    if (m_DnD) {
       delete m_DnD;
+      m_DnD = NULL;
    }
    if (m_detWnd) {
       delete m_detWnd;
-   }
-   if (m_detWndFull) {
-      delete m_detWndFull;
+      m_detWnd = NULL;
    }
 out:
    if (reply) {
       free(reply);
    }
-   return;
+   return ret;
 }
 
 
 /**
  *
  * Setup targets we support, claim ourselves as a drag destination, and
- * register callbacks for Gdk drag and drop callbacks the platform will
+ * register callbacks for Gtk+ drag and drop callbacks the platform will
  * send to us.
  */
 
@@ -248,12 +243,13 @@ DnDUI::SetTargetsAndCallbacks()
     */
    m_detWnd->drag_dest_set(targets, Gtk::DEST_DEFAULT_MOTION,
                            Gdk::ACTION_COPY | Gdk::ACTION_MOVE);
-   m_detWnd->signal_drag_leave().connect(sigc::mem_fun(this, &DnDUI::LocalDragLeaveCB));
-   m_detWnd->signal_drag_motion().connect(sigc::mem_fun(this, &DnDUI::LocalDragMotionCB));
-   m_detWnd->signal_drag_drop().connect(sigc::mem_fun(this, &DnDUI::LocalDragDropCB));
-   m_detWnd->signal_drag_data_received().connect(sigc::mem_fun(this, &DnDUI::LocalDragDataReceivedCB));
+   m_detWnd->signal_drag_leave().connect(sigc::mem_fun(this, &DnDUI::GtkDestDragLeaveCB));
+   m_detWnd->signal_drag_motion().connect(sigc::mem_fun(this, &DnDUI::GtkDestDragMotionCB));
+   m_detWnd->signal_drag_drop().connect(sigc::mem_fun(this, &DnDUI::GtkDestDragDropCB));
+   m_detWnd->signal_drag_data_received().connect(sigc::mem_fun(this, &DnDUI::GtkDestDragDataReceivedCB));
 }
 
+/* Begin of callbacks issued by common layer code */
 
 /**
  *
@@ -261,33 +257,20 @@ DnDUI::SetTargetsAndCallbacks()
  */
 
 void
-DnDUI::ResetUIStateCB(void)
+DnDUI::CommonResetCB(void)
 {
-   m_GHDnDHostStatus = false;
-   m_GHDnDAction = (Gdk::DragAction)0;
+   Debug("%s: entering\n", __FUNCTION__);
    m_GHDnDDataReceived = false;
-   m_GHDnDDropOccurred = false;
    m_HGGetDataInProgress = false;
-   m_VMIsSource = false;
    m_GHDnDInProgress = false;
-   m_feedbackChanged.disconnect();
-   m_effect = DROP_UNKNOWN;
+   m_effect = DROP_NONE;
+   m_inHGDrag = false;
+   m_dc = NULL;
+   m_isFileDnD = false;
    RemoveBlock();
 }
 
 
-/**
- * Set block control member.
- *
- * @param[in] block control as setup by vmware-user.
- */
-
-void
-DnDUI::SetBlockControl(DnDBlockControl *blockCtrl)
-{
-   m_blockCtrl = blockCtrl;
-}
-
 /* Source functions for HG DnD. */
 
 /**
@@ -299,7 +282,7 @@ DnDUI::SetBlockControl(DnDBlockControl *blockCtrl)
  */
 
 void
-DnDUI::RemoteDragStartCB(const CPClipboard *clip, std::string stagingDir)
+DnDUI::CommonDragStartCB(const CPClipboard *clip, std::string stagingDir)
 {
    Glib::RefPtr<Gtk::TargetList> targets;
    Gdk::DragAction actions;
@@ -310,6 +293,14 @@ DnDUI::RemoteDragStartCB(const CPClipboard *clip, std::string stagingDir)
 
    Debug("%s: enter\n", __FUNCTION__);
 
+   /*
+    * Before the DnD, we should make sure that the mouse is released
+    * otherwise it may be another DnD, not ours. Send a release, then
+    * a press here to cover this case.
+    */
+   SendFakeXEvents(false, true, false, false, false, 0, 0);
+   SendFakeXEvents(true, true, true, false, true, 0, 0);
+
    /*
     * Construct the target and action list, as well as a fake motion notify
     * event that's consistent with one that would typically start a drag.
@@ -332,7 +323,7 @@ DnDUI::RemoteDragStartCB(const CPClipboard *clip, std::string stagingDir)
    }
 
    if (CPClipboard_ItemExists(&m_clipboard, CPFORMAT_FILECONTENTS)) {
-      if (LocalPrepareFileContentsDrag()) {
+      if (WriteFileContentsToStagingDir()) {
          targets->add(Glib::ustring(DRAG_TARGET_NAME_URI_LIST));
       }
    }
@@ -354,7 +345,7 @@ DnDUI::RemoteDragStartCB(const CPClipboard *clip, std::string stagingDir)
    /* TODO set the x/y coords to the actual drag initialization point. */
    event.type = GDK_MOTION_NOTIFY;
    event.window = m_detWnd->get_window()->gobj();
-   event.send_event = FALSE;
+   event.send_event = false;
    event.time = GDK_CURRENT_TIME;
    event.x = 10;
    event.y = 10;
@@ -370,291 +361,112 @@ DnDUI::RemoteDragStartCB(const CPClipboard *clip, std::string stagingDir)
    m_blockAdded = false;
    m_isFileDnD = false;
    SourceDragStartDone();
+   /* Initialize host hide feedback to DROP_NONE. */
+   m_effect = DROP_NONE;
+   SourceUpdateFeedback(m_effect);
 }
 
 
 /**
  *
- * Try to extract file contents from m_clipboard. Write all files to a
- * temporary staging directory. Construct uri list.
- *
- * @return TRUE if success, FALSE otherwise.
+ * Cancel current HG DnD.
  */
 
-bool
-DnDUI::LocalPrepareFileContentsDrag(void)
+void
+DnDUI::CommonSourceCancelCB(void)
 {
-   void *buf = NULL;
-   size_t sz = 0;
-   XDR xdrs;
-   CPFileContents fileContents;
-   CPFileContentsList *contentsList = NULL;
-   size_t nFiles = 0;
-   CPFileItem *fileItem = NULL;
-   Unicode tempDir = NULL;
-   size_t i = 0;
-   bool ret = FALSE;
-
-   if (!CPClipboard_GetItem(&m_clipboard, CPFORMAT_FILECONTENTS, &buf, &sz)) {
-      return false;
-   }
-
-   /* Extract file contents from buf. */
-   xdrmem_create(&xdrs, (char *)buf, sz, XDR_DECODE);
-   memset(&fileContents, 0, sizeof fileContents);
-
-   if (!xdr_CPFileContents(&xdrs, &fileContents)) {
-      Debug("%s: xdr_CPFileContents failed.\n", __FUNCTION__);
-      xdr_destroy(&xdrs);
-      return false;
-   }
-   xdr_destroy(&xdrs);
-
-   contentsList = fileContents.CPFileContents_u.fileContentsV1;
-   if (!contentsList) {
-      Debug("%s: invalid contentsList.\n", __FUNCTION__);
-      goto exit;
-   }
-
-   nFiles = contentsList->fileItem.fileItem_len;
-   if (0 == nFiles) {
-      Debug("%s: invalid nFiles.\n", __FUNCTION__);
-      goto exit;
-   }
-
-   fileItem = contentsList->fileItem.fileItem_val;
-   if (!fileItem) {
-      Debug("%s: invalid fileItem.\n", __FUNCTION__);
-      goto exit;
-   }
+   Debug("%s: entering\n", __FUNCTION__);
 
    /*
-    * Write files into a temporary staging directory. These files will be moved
-    * to final destination, or deleted on next reboot.
+    * Force the window to show, position the mouse over it, and release.
+    * Seems like moving the window to 0, 0 eliminates frequently observed
+    * flybacks when we cancel as user moves mouse in and out of destination
+    * window in a H->G DnD.
     */
-   tempDir = DnD_CreateStagingDirectory();
-   if (!tempDir) {
-      Debug("%s: DnD_CreateStagingDirectory failed.\n", __FUNCTION__);
-      goto exit;
-   }
-
-   m_HGFileContentsUriList = "";
-
-   for (i = 0; i < nFiles; i++) {
-      utf::string fileName;
-      utf::string filePathName;
-      VmTimeType createTime = -1;
-      VmTimeType accessTime = -1;
-      VmTimeType writeTime = -1;
-      VmTimeType attrChangeTime = -1;
-
-      if (!fileItem[i].cpName.cpName_val ||
-          0 == fileItem[i].cpName.cpName_len) {
-         Debug("%s: invalid fileItem[%"FMTSZ"u].cpName.\n", __FUNCTION__, i);
-         goto exit;
-      }
-
-      /*
-       * '\0' is used as directory separator in cross-platform name. Now turn
-       * '\0' in data into DIRSEPC.
-       *
-       * Note that we don't convert the final '\0' into DIRSEPC so the string
-       * is NUL terminated.
-       */
-      CPNameUtil_CharReplace(fileItem[i].cpName.cpName_val,
-                             fileItem[i].cpName.cpName_len - 1,
-                             '\0',
-                             DIRSEPC);
-      fileName = fileItem[i].cpName.cpName_val;
-      filePathName = tempDir;
-      filePathName += DIRSEPS + fileName;
-
-      if (fileItem[i].validFlags & CP_FILE_VALID_TYPE &&
-          CP_FILE_TYPE_DIRECTORY == fileItem[i].type) {
-         if (!File_CreateDirectory(filePathName.c_str())) {
-            goto exit;
-         }
-         Debug("%s: created directory [%s].\n",
-               __FUNCTION__, filePathName.c_str());
-      } else if (fileItem[i].validFlags & CP_FILE_VALID_TYPE &&
-                 CP_FILE_TYPE_REGULAR == fileItem[i].type) {
-         FileIODescriptor file;
-         FileIOResult fileErr;
-
-         FileIO_Invalidate(&file);
-
-         fileErr = FileIO_Open(&file,
-                               filePathName.c_str(),
-                               FILEIO_ACCESS_WRITE,
-                               FILEIO_OPEN_CREATE_EMPTY);
-         if (!FileIO_IsSuccess(fileErr)) {
-            goto exit;
-         }
-
-         fileErr = FileIO_Write(&file,
-                                fileItem[i].content.content_val,
-                                fileItem[i].content.content_len,
-                                NULL);
-
-         FileIO_Close(&file);
-         Debug("%s: created file [%s].\n",
-               __FUNCTION__, filePathName.c_str());
-      } else {
-         /*
-          * Right now only Windows can provide CPFORMAT_FILECONTENTS data.
-          * Symlink file is not expected. Continue with next file if the
-          * type is not valid.
-          */
-         continue;
-      }
-
-      /* Update file time attributes. */
-      createTime = fileItem->validFlags & CP_FILE_VALID_CREATE_TIME ?
-         fileItem->createTime: -1;
-      accessTime = fileItem->validFlags & CP_FILE_VALID_ACCESS_TIME ?
-         fileItem->accessTime: -1;
-      writeTime = fileItem->validFlags & CP_FILE_VALID_WRITE_TIME ?
-         fileItem->writeTime: -1;
-      attrChangeTime = fileItem->validFlags & CP_FILE_VALID_CHANGE_TIME ?
-         fileItem->attrChangeTime: -1;
-
-      if (!File_SetTimes(filePathName.c_str(),
-                         createTime,
-                         accessTime,
-                         writeTime,
-                         attrChangeTime)) {
-         /* Not a critical error, only log it. */
-         Debug("%s: File_SetTimes failed with file [%s].\n",
-               __FUNCTION__, filePathName.c_str());
-      }
-
-      /* Update file permission attributes. */
-      if (fileItem->validFlags & CP_FILE_VALID_PERMS) {
-         if (Posix_Chmod(filePathName.c_str(),
-                         fileItem->permissions) < 0) {
-            /* Not a critical error, only log it. */
-            Debug("%s: Posix_Chmod failed with file [%s].\n",
-                  __FUNCTION__, filePathName.c_str());
-         }
-      }
-
-      /*
-       * If there is no DIRSEPC inside the fileName, this file/directory is a
-       * top level one. We only put top level name into uri list.
-       */
-      if (fileName.find(DIRSEPS, 0) == utf::string::npos) {
-         m_HGFileContentsUriList += "file://" + filePathName + "\r\n";
-      }
-   }
-   Debug("%s: created uri list [%s].\n",
-         __FUNCTION__, m_HGFileContentsUriList.c_str());
-   ret = true;
-
-exit:
-   xdr_free((xdrproc_t) xdr_CPFileContents, (char *)&fileContents);
-   if (tempDir && !ret) {
-      DnD_DeleteStagingFiles(tempDir, FALSE);
-   }
-   free(tempDir);
-   return ret;
+   CommonUpdateDetWndCB(true, 0, 0);
+   SendFakeXEvents(true, true, false, true, true, 0, 0);
+   CommonUpdateDetWndCB(false, 0, 0);
+   m_inHGDrag = false;
+   m_HGGetDataInProgress = false;
+   m_effect = DROP_NONE;
+   RemoveBlock();
 }
 
 
 /**
  *
- * Tell host that we are done with HG DnD initialization.
- */
-
-void
-DnDUI::SourceDragStartDone(void)
-{
-   Debug("%s: enter\n", __FUNCTION__);
-   m_inHGDrag = true;
-   m_DnD->HGDragStartDone();
-}
-
-
-/**
+ * Handle common layer private drop CB.
  *
- * Handler for when the guest provides drag status during a host->guest
- * operation. This will change as we drag over different things in the guest.
- * Here, we map what is report to a Gdk drag action, and then forward this
- * status value to the Gdk drag context.
+ * @param[in] x position to release the mouse button (ignored).
+ * @param[in] y position to release the mouse button (ignored).
  *
- * @param[in] effect drop effect
- * @param[in] gc Gdk drag context object, to which status is forwarded.
+ * @note We ignore the coordinates, because we just need to release the mouse
+ * in its current position.
  */
 
 void
-DnDUI::SourceFeedbackChangedCB(DND_DROPEFFECT effect,
-                               const Glib::RefPtr<Gdk::DragContext> dc)
+DnDUI::CommonDestPrivateDropCB(int32 x,
+                               int32 y)
 {
-   Debug("%s: enter\n", __FUNCTION__);
-   if (effect == DROP_NONE) {
-      m_GHDnDAction = (Gdk::DragAction)0;
-   } else if (effect & DROP_COPY) {
-      m_GHDnDAction = Gdk::ACTION_COPY;
-   } else if (effect & DROP_MOVE) {
-      m_GHDnDAction = Gdk::ACTION_MOVE;
-   } else if (effect & DROP_LINK) {
+   Debug("%s: entering\n", __FUNCTION__);
+   /* Unity manager in host side may already send the drop into guest. */
+   if (m_GHDnDInProgress) {
+
       /*
-       * We don't do link.
+       * Release the mouse button.
        */
-      m_GHDnDAction = Gdk::ACTION_COPY;
-   } else {
-      m_GHDnDAction = (Gdk::DragAction)0;
+      SendFakeXEvents(false, true, false, false, false, 0, 0);
    }
-   m_GHDnDHostStatus = !!effect;
-
-   dc->drag_status(m_GHDnDAction, GDK_CURRENT_TIME);
+   CommonResetCB();
 }
 
 
 /**
  *
- * Cancel current HG DnD.
+ * Cancel current DnD (G->H only).
  */
 
 void
-DnDUI::SourceCancelCB(void)
+DnDUI::CommonDestCancelCB(void)
 {
    Debug("%s: entering\n", __FUNCTION__);
-   m_inHGDrag = false;
-   m_HGGetDataInProgress = false;
-   m_effect = DROP_UNKNOWN;
-   RemoveBlock();
-}
-
-
-/**
- *
- * Cancel current GH DnD.
- */
+   /* Unity manager in host side may already send the drop into guest. */
+   if (m_GHDnDInProgress) {
+      CommonUpdateDetWndCB(true, 0, 0);
 
-void
-DnDUI::GHCancelCB(void)
-{
-   ResetUIStateCB();
+      /*
+       * Show the window, move it to the mouse position, and release the
+       * mouse button.
+       */
+      SendFakeXEvents(true, true, false, true, false, 0, 0);
+   }
+   m_destDropTime = GetTimeInMillis();
+   CommonResetCB();
 }
 
 
 /**
  *
- * Got drop from host side. Add block first then host can simulate the drop
- * in the guest.
+ * Got drop from host side. Release the mouse button in the detection window
  */
 
 void
-DnDUI::SourceDropCB(void)
+DnDUI::CommonSourceDropCB(void)
 {
    Debug("%s: enter\n", __FUNCTION__);
-   m_inHGDrag = false;
+   CommonUpdateDetWndCB(true, 0, 0);
+
+   /*
+    * Move the mouse to the saved coordinates, and release the mouse button.
+    */
+   SendFakeXEvents(false, true, false, false, true, m_mousePosX, m_mousePosY);
+   CommonUpdateDetWndCB(false, 0, 0);
 }
 
 
 /**
  *
- * Callback when HG file transfer is done, which finishes the file
+ * Callback when file transfer is done, which finishes the file
  * copying from host to guest staging directory.
  *
  * @param[in] success if true, transfer was successful
@@ -662,51 +474,30 @@ DnDUI::SourceDropCB(void)
  */
 
 void
-DnDUI::GetLocalFilesDoneCB(bool success,
-                           std::vector<uint8> stagingDir)
+DnDUI::CommonSourceFileCopyDoneCB(bool success,
+                                  std::vector<uint8> stagingDir)
 {
    Debug("%s: %s\n", __FUNCTION__, success ? "success" : "failed");
    /* Copied files are already removed in common layer. */
    stagingDir.clear();
-   Reset();
+   CommonResetCB();
    m_HGGetDataInProgress = false;
 }
 
 
-/* Target functions for GH DnD. */
-
 /**
  *
- * This is triggered when user drags valid data from guest to host. Try to
- * get clip data and notify host to start GH DnD.
+ * Shows/hides drag detection windows based on the mask.
+ *
+ * @param[in] bShow if true, show the window, else hide it.
+ * @param[in] x x-coordinate to which the detection window needs to be moved
+ * @param[in] y y-coordinate to which the detection window needs to be moved
  */
 
 void
-DnDUI::TargetDragEnter(void)
-{
-   Debug("%s: entering\n", __FUNCTION__);
-
-   /* Check if there is valid data with current detection window. */
-   if (!CPClipboard_IsEmpty(&m_clipboard)) {
-      Debug("%s: got valid data from detWnd.\n", __FUNCTION__);
-      m_DnD->DragEnter(&m_clipboard);
-   }
-}
-
-
-/**
- *
- * Shows/hides drag detection windows based on the mask.
- *
- * @param[in] bShow if true, show the window, else hide it.
- * @param[in] x x-coordinate to which the detection window needs to be moved
- * @param[in] y y-coordinate to which the detection window needs to be moved
- */
-
-void
-DnDUI::UpdateDetWndCB(bool bShow,
-                      int32 x,
-                      int32 y)
+DnDUI::CommonUpdateDetWndCB(bool bShow,
+                            int32 x,
+                            int32 y)
 {
    /* If the window is being shown, move it to the right place. */
    if (bShow) {
@@ -715,16 +506,20 @@ DnDUI::UpdateDetWndCB(bool bShow,
 
       m_detWnd->Show();
       m_detWnd->Raise();
-      m_detWnd->SetGeometry(x, y, 2 * DRAG_DET_WINDOW_WIDTH, 2 * DRAG_DET_WINDOW_WIDTH);
+      m_detWnd->SetGeometry(x, y, DRAG_DET_WINDOW_WIDTH * 2, DRAG_DET_WINDOW_WIDTH * 2);
+      Debug("%s: show at (%d, %d, %d, %d)\n", __FUNCTION__, x, y, DRAG_DET_WINDOW_WIDTH * 2, DRAG_DET_WINDOW_WIDTH * 2);
       /*
        * Wiggle the mouse here. Especially for G->H DnD, this improves
        * reliability of making the drag escape the guest window immensly.
        * Stolen from the legacy V2 DnD code.
        */
 
-      DnDHGFakeMove(x, y);
+      SendFakeMouseMove(x, y);
+      m_detWnd->SetIsVisible(true);
    } else {
+      Debug("%s: hide\n", __FUNCTION__);
       m_detWnd->Hide();
+      m_detWnd->SetIsVisible(false);
    }
 }
 
@@ -735,38 +530,92 @@ DnDUI::UpdateDetWndCB(bool bShow,
  *
  * @param[in] bShow if true, show the window, else hide it.
  * @param[in] unityWndId active front window
+ * @param[in] bottom if true, adjust the z-order to be bottom most.
  */
 
 void
-DnDUI::UpdateUnityDetWndCB(bool bShow,
-                           uint32 unityWndId)
+DnDUI::CommonUpdateUnityDetWndCB(bool bShow,
+                                 uint32 unityWndId,
+                                 bool bottom)
 {
-   if (bShow && unityWndId > 0) {
-      int width = m_detWndFull->GetScreenWidth();
-      int height = m_detWndFull->GetScreenHeight();
-      m_detWndFull->SetGeometry(0, 0, width, height);
-      m_detWndFull->Lower();
-      m_detWndFull->Show();
+   if (bShow && ((unityWndId > 0) || bottom)) {
+      int width = m_detWnd->GetScreenWidth();
+      int height = m_detWnd->GetScreenHeight();
+      m_detWnd->SetGeometry(0, 0, width, height);
+      m_detWnd->Show();
+      if (bottom) {
+         m_detWnd->Lower();
+      }
+
+      Debug("%s: show, (0, 0, %d, %d)\n", __FUNCTION__, width, height);
    } else {
-      m_detWndFull->Hide();
+      if (m_detWnd->GetIsVisible() == true) {
+         if (m_unityMode) {
+
+            /*
+             * Show and move detection window to current mouse position
+             * and resize.
+             */
+            SendFakeXEvents(true, false, true, true, false, 0, 0);
+         }
+      } else {
+         m_detWnd->Hide();
+         Debug("%s: hide\n", __FUNCTION__);
+      }
    }
 }
 
 
 /**
  *
- * Reset the UI independent DnD layer.
+ * Move detection windows to current cursor position.
  */
 
 void
-DnDUI::Reset(void)
+DnDUI::CommonMoveDetWndToMousePos(void)
 {
-   Debug("%s: entering\n", __FUNCTION__);
-   if (m_DnD) {
-      m_DnD->ResetDnD();
+   SendFakeXEvents(true, false, true, true, false, 0, 0);
+}
+
+
+/**
+ *
+ * Handle request from common layer to update mouse position.
+ *
+ * @param[in] x x coordinate of pointer
+ * @param[in] y y coordinate of pointer
+ */
+
+void
+DnDUI::CommonUpdateMouseCB(int32 x,
+                           int32 y)
+{
+   // Position the pointer, and record its position.
+
+   SendFakeXEvents(false, false, false, false, true, x, y);
+   m_mousePosX = x;
+   m_mousePosY = y;
+
+   if (m_dc && !m_GHDnDInProgress) {
+
+      // If we are the context of a DnD, send DnD feedback to the source.
+
+      DND_DROPEFFECT effect;
+      effect = ToDropEffect((Gdk::DragAction)(m_dc->action));
+      if (effect != m_effect) {
+         m_effect = effect;
+         Debug("%s: Updating feedback\n", __FUNCTION__);
+         SourceUpdateFeedback(m_effect);
+      }
    }
 }
 
+/* Beginning of Gtk+ Callbacks */
+
+/*
+ * Source callbacks from Gtk+. Most are seen only when we are acting as a
+ * drag source.
+ */
 
 /**
  *
@@ -786,39 +635,46 @@ DnDUI::Reset(void)
  * we only return false if we don't recognize the types being offered. We
  * return true otherwise, even if we don't accept the drag right now for some
  * other reason.
+ *
+ * @note you may see this callback during DnD when detection window is acting
+ * as a source. In that case it will be ignored. In a future refactoring,
+ * we will try and avoid this.
  */
 
 bool
-DnDUI::LocalDragMotionCB(const Glib::RefPtr<Gdk::DragContext> &dc,
-                         int x,
-                         int y,
-                         guint time)
+DnDUI::GtkDestDragMotionCB(const Glib::RefPtr<Gdk::DragContext> &dc,
+                           int x,
+                           int y,
+                           guint timeValue)
 {
-   DND_DROPEFFECT effect;
-
-   effect = ToDropEffect(dc->get_action());
-   if (effect != m_effect) {
-      m_effect = effect;
-      Debug("%s: Updating feedback\n", __FUNCTION__);
-      SourceUpdateFeedback(m_effect);
-   }
-
    /*
     * If this is a Host to Guest drag, we are done here, so return.
     */
+   Debug("%s: enter", __FUNCTION__);
+
+   unsigned long curTime = GetTimeInMillis();
+   if (curTime - m_destDropTime <= 1000) {
+      Debug("%s: ignored %ld %ld %ld\n", __FUNCTION__,
+            curTime, m_destDropTime, curTime - m_destDropTime);
+      return true;
+   }
 
-   if (m_inHGDrag) {
+   Debug("%s: not ignored %ld %ld %ld\n", __FUNCTION__,
+         curTime, m_destDropTime, curTime - m_destDropTime);
+
+   if (m_inHGDrag || m_HGGetDataInProgress) {
+      Debug("%s: ignored not in hg drag or not getting hg data\n", __FUNCTION__);
       return true;
    }
 
    Gdk::DragAction srcActions;
    Gdk::DragAction suggestedAction;
+   Gdk::DragAction dndAction = (Gdk::DragAction)0;
    Glib::ustring target = m_detWnd->drag_dest_find_target(dc);
 
    if (!m_DnD->IsDnDAllowed()) {
       Debug("%s: No dnd allowed!\n", __FUNCTION__);
-      m_GHDnDAction = (Gdk::DragAction)0;
-      dc->drag_status(m_GHDnDAction, time);
+      dc->drag_status(dndAction, timeValue);
       return true;
    }
 
@@ -847,6 +703,8 @@ DnDUI::LocalDragMotionCB(const Glib::RefPtr<Gdk::DragContext> &dc,
       return true;
    }
 
+   m_dc = dc->gobj();
+
    if (target != "") {
       /*
        * We give preference to the suggested action from the source, and prefer
@@ -855,19 +713,20 @@ DnDUI::LocalDragMotionCB(const Glib::RefPtr<Gdk::DragContext> &dc,
       suggestedAction = dc->get_suggested_action();
       srcActions = dc->get_actions();
       if (suggestedAction == Gdk::ACTION_COPY || suggestedAction == Gdk::ACTION_MOVE) {
-         m_GHDnDAction = suggestedAction;
+         dndAction = suggestedAction;
       } else if (srcActions & Gdk::ACTION_COPY) {
-         m_GHDnDAction= Gdk::ACTION_COPY;
+         dndAction= Gdk::ACTION_COPY;
       } else if (srcActions & Gdk::ACTION_MOVE) {
-         m_GHDnDAction = Gdk::ACTION_MOVE;
+         dndAction = Gdk::ACTION_MOVE;
       } else {
-         m_GHDnDAction = (Gdk::DragAction)0;
+         dndAction = (Gdk::DragAction)0;
       }
    } else {
-      m_GHDnDAction = (Gdk::DragAction)0;
+      dndAction = (Gdk::DragAction)0;
    }
 
-   if (m_GHDnDAction != (Gdk::DragAction)0) {
+   if (dndAction != (Gdk::DragAction)0) {
+      dc->drag_status(dndAction, timeValue);
       if (!m_GHDnDInProgress) {
          Debug("%s: new drag, need to get data for host\n", __FUNCTION__);
          /*
@@ -876,19 +735,9 @@ DnDUI::LocalDragMotionCB(const Glib::RefPtr<Gdk::DragContext> &dc,
           * retrieve the drop data.
           */
          m_GHDnDInProgress = true;
-         m_GHDnDAction = (Gdk::DragAction)0;
          /* only begin drag enter after we get the data */
          /* Need to grab all of the data. */
-         m_detWnd->drag_get_data(dc, target, time);
-      } else if (m_GHDnDDataReceived) {
-         Debug("%s: m_GHDnDDataReceived, setting mouse position\n", __FUNCTION__);
-         m_DnD->SetMouse(x, y, true);
-
-         if (m_GHDnDHostStatus) {
-            /* Got host response, respond with a proper drag status. */
-            Debug("%s: Existing status, calling drag_status()\n", __FUNCTION__);
-            dc->drag_status(m_GHDnDAction, time);
-         }
+         m_detWnd->drag_get_data(dc, target, timeValue);
       } else {
          Debug("%s: Multiple drag motions before gh data has been received.\n",
                __FUNCTION__);
@@ -903,99 +752,38 @@ DnDUI::LocalDragMotionCB(const Glib::RefPtr<Gdk::DragContext> &dc,
 
 /**
  *
- * Got feedback from our DropSource, send it over to host. Called by
- * drag motion callback.
- *
- * @param[in] effect feedback to send to the UI-independent DnD layer.
- */
-
-void
-DnDUI::SourceUpdateFeedback(DND_DROPEFFECT effect)
-{
-   Debug("%s: entering\n", __FUNCTION__);
-   m_DnD->SetFeedback(effect);
-}
-
-
-/**
- *
- * "drag_leave" signal handler for GTK. We can't clean up the drop
- *  operation here, because it might be part of a drop. See the
- *  LocalDragLeaveTimeout() function for more details.
+ * "drag_leave" signal handler for GTK. Log the reception of this signal,
+ * but otherwise unhandled in our implementation.
  *
  *  @param[in] dc drag context
  *  @param[in] time time of the drag
  */
 
 void
-DnDUI::LocalDragLeaveCB(const Glib::RefPtr<Gdk::DragContext> &dc, guint time)
+DnDUI::GtkDestDragLeaveCB(const Glib::RefPtr<Gdk::DragContext> &dc,
+                          guint time)
 {
    Debug("%s: enter\n", __FUNCTION__);
-   m_feedbackChanged.disconnect();
-   dc->drag_finish(true, dc->get_action() == Gdk::ACTION_MOVE, time);
-   ResetUIStateCB();
 }
 
 
+/*
+ * Gtk+ callbacks that are seen when we are a drag source.
+ */
+
 /**
  *
  * "drag_begin" signal handler for GTK.
- * Added to help understand Gtk+ state when looking at logs.
  *
  * @param[in] context drag context
  */
 
 void
-DnDUI::LocalDragBeginCB(const Glib::RefPtr<Gdk::DragContext>& context)
-{
-   Debug("%s: enter\n", __FUNCTION__);
-}
-
-
-/**
- *
- * "drag_drop" signal handler for GTK. Send the drop to the host (by
- * way of the backdoor), then tell the host to get the files.
- *
- * @param[in] dc drag context
- * @param[in] x x location of the drop
- * @param[in] y y location of the drop
- * @param[in] time timestamp for the drop
- *
- * @return true on success, false otherwise.
- */
-
-bool
-DnDUI::LocalDragDropCB(const Glib::RefPtr<Gdk::DragContext> &dc,
-                       int x,
-                       int y,
-                       guint time)
+DnDUI::GtkSourceDragBeginCB(const Glib::RefPtr<Gdk::DragContext>& context)
 {
-   Debug("%s: enter x %d y %d\n", __FUNCTION__, x, y);
-
-   Glib::ustring target;
-
-   target = m_detWnd->drag_dest_find_target(dc);
-
-   if (m_VMIsSource) {
-      Debug("%s: Dropping in same vm.\n", __FUNCTION__);
-      /* Act as a drop */
-      ResetUIStateCB();
-      return false;
-   }
-
-   if (target == "") {
-      Debug("%s: No valid data on clipboard.\n", __FUNCTION__);
-      m_DnD->ResetDnD();
-      return false;
-   }
-
-   if (CPClipboard_IsEmpty(&m_clipboard)) {
-      Debug("%s: No valid data on m_clipboard.\n", __FUNCTION__);
-      m_DnD->ResetDnD();
-      return false;
-   }
-   return true;
+   Debug("%s: enter dc %p, m_dc %p\n", __FUNCTION__,
+         context ? context->gobj() : NULL, m_dc ? m_dc : NULL);
+   m_dc = context->gobj();
 }
 
 
@@ -1014,10 +802,10 @@ DnDUI::LocalDragDropCB(const Glib::RefPtr<Gdk::DragContext> &dc,
  */
 
 void
-DnDUI::LocalDragDataGetCB(const Glib::RefPtr<Gdk::DragContext> &dc,
-                          Gtk::SelectionData& selection_data,
-                          guint info,
-                          guint time)
+DnDUI::GtkSourceDragDataGetCB(const Glib::RefPtr<Gdk::DragContext> &dc,
+                              Gtk::SelectionData& selection_data,
+                              guint info,
+                              guint time)
 {
    size_t index = 0;
    std::string str;
@@ -1036,6 +824,7 @@ DnDUI::LocalDragDataGetCB(const Glib::RefPtr<Gdk::DragContext> &dc,
 
    if (!m_inHGDrag) {
       Debug("%s: not in drag, return\n", __FUNCTION__);
+      return;
    }
 
    if (target == DRAG_TARGET_NAME_URI_LIST &&
@@ -1102,6 +891,8 @@ DnDUI::LocalDragDataGetCB(const Glib::RefPtr<Gdk::DragContext> &dc,
          m_HGGetDataInProgress = true;
          m_isFileDnD = true;
          AddBlock();
+      } else {
+         Debug("%s: not calling AddBlock\n", __FUNCTION__);
       }
       selection_data.set(DRAG_TARGET_NAME_URI_LIST, uriList.c_str());
       Debug("%s: exit\n", __FUNCTION__);
@@ -1139,26 +930,43 @@ DnDUI::LocalDragDataGetCB(const Glib::RefPtr<Gdk::DragContext> &dc,
    /* Can not get any valid data, cancel this HG DnD. */
    Debug("%s: no valid data for HG DnD\n", __FUNCTION__);
    m_DnD->SourceCancel();
-   ResetUIStateCB();
+   CommonResetCB();
 }
 
 
 /**
  *
- * "drag_end" handler for GTK.
+ * "drag_end" handler for GTK. Received by drag source.
  *
  * @param[in] dc drag state
  */
 
 void
-DnDUI::LocalDragEndCB(const Glib::RefPtr<Gdk::DragContext> &dc)
+DnDUI::GtkSourceDragEndCB(const Glib::RefPtr<Gdk::DragContext> &dc)
 {
-   Debug("%s: enter\n", __FUNCTION__);
+   Debug("%s: entering dc %p, m_dc %p\n", __FUNCTION__,
+         dc ? dc->gobj() : NULL, m_dc ? m_dc : NULL);
+
+   /*
+    * We may see a drag end for the previous DnD, but after a new
+    * DnD has started. If so, ignore it.
+    */
+   if (m_dc && dc && (m_dc != dc->gobj())) {
+      Debug("%s: got old dc (new DnD started), ignoring\n", __FUNCTION__);
+      return;
+   }
+
+   /*
+    * If we are a file DnD, don't call CommonResetCB() here, since
+    * we will do so in the fileCopyDoneChanged callback.
+    */
    if (!m_isFileDnD) {
-      Reset();
+      CommonResetCB();
    }
+   m_inHGDrag = false;
 }
 
+/* Gtk+ callbacks seen when we are a drag destination. */
 
 /**
  *
@@ -1177,15 +985,15 @@ DnDUI::LocalDragEndCB(const Glib::RefPtr<Gdk::DragContext> &dc)
  */
 
 void
-DnDUI::LocalDragDataReceivedCB(const Glib::RefPtr<Gdk::DragContext> &dc,
-                               int x,
-                               int y,
-                               const Gtk::SelectionData& sd,
-                               guint info,
-                               guint time)
+DnDUI::GtkDestDragDataReceivedCB(const Glib::RefPtr<Gdk::DragContext> &dc,
+                                 int x,
+                                 int y,
+                                 const Gtk::SelectionData& sd,
+                                 guint info,
+                                 guint time)
 {
    Debug("%s: enter\n", __FUNCTION__);
-   /* The HG DnD may already finish before we got response. */
+   /* The GH DnD may already finish before we got response. */
    if (!m_GHDnDInProgress) {
       Debug("%s: not valid\n", __FUNCTION__);
       return;
@@ -1195,11 +1003,18 @@ DnDUI::LocalDragDataReceivedCB(const Glib::RefPtr<Gdk::DragContext> &dc,
 
    /*
     * Try to get data provided from the source.  If we cannot get any data,
-    * there is no need to inform the guest of anything.
+    * there is no need to inform the guest of anything. If there is no data,
+    * reset, so that the next drag_motion callback that we see will be allowed
+    * to request data again.
     */
-   LocalGetSelection(sd);
+   if (SetCPClipboardFromGtk(sd) == false) {
+      Debug("%s: Failed to set CP clipboard.\n", __FUNCTION__);
+      CommonResetCB();
+      return;
+   }
    if (CPClipboard_IsEmpty(&m_clipboard)) {
       Debug("%s: Failed getting item.\n", __FUNCTION__);
+      CommonResetCB();
       return;
    }
 
@@ -1218,37 +1033,66 @@ DnDUI::LocalDragDataReceivedCB(const Glib::RefPtr<Gdk::DragContext> &dc,
       Debug("%s: Drag entering.\n", __FUNCTION__);
       m_GHDnDDataReceived = true;
       TargetDragEnter();
-      m_feedbackChanged = m_DnD->updateFeedbackChanged.connect(
-         sigc::bind(sigc::mem_fun(this, &DnDUI::SourceFeedbackChangedCB), dc));
-   } else if (m_GHDnDDropOccurred) {
-      Debug("%s: Drag dropping.\n", __FUNCTION__);
-      m_DnD->TargetDrop(&m_clipboard, x, y);
-      dc->drag_finish(true, dc->get_action() == Gdk::ACTION_MOVE, time);
-      /*
-       * Can't use ResetUIStateCB because file transfer state should not be
-       * cleared.
-       */
-      m_GHDnDDataReceived = false;
-      m_GHDnDAction = (Gdk::DragAction)0;
-      m_GHDnDHostStatus = false;
-      m_GHDnDInProgress = false;
-      m_feedbackChanged.disconnect();
    } else {
-      Debug("%s: neither m_GHDnDDropOccurred, nor !m_GHDnDDataReceived\n",
-         __FUNCTION__);
+      Debug("%s: not !m_GHDnDDataReceived\n", __FUNCTION__);
+   }
+}
+
+
+/**
+ *
+ * "drag_drop" signal handler for GTK. Send the drop to the host (by
+ * way of the backdoor), then tell the host to get the files.
+ *
+ * @param[in] dc drag context
+ * @param[in] x x location of the drop
+ * @param[in] y y location of the drop
+ * @param[in] time timestamp for the drop
+ *
+ * @return true on success, false otherwise.
+ */
+
+bool
+DnDUI::GtkDestDragDropCB(const Glib::RefPtr<Gdk::DragContext> &dc,
+                         int x,
+                         int y,
+                         guint time)
+{
+   Debug("%s: enter x %d y %d\n", __FUNCTION__, x, y);
+
+   Glib::ustring target;
+
+   target = m_detWnd->drag_dest_find_target(dc);
+   Debug("%s: calling drag_finish\n", __FUNCTION__);
+   dc->drag_finish(true, false, time);
+
+   if (target == "") {
+      Debug("%s: No valid data on clipboard.\n", __FUNCTION__);
+      return false;
    }
+
+   if (CPClipboard_IsEmpty(&m_clipboard)) {
+      Debug("%s: No valid data on m_clipboard.\n", __FUNCTION__);
+      return false;
+   }
+
+   return true;
 }
 
+/* General utility functions */
 
 /**
  *
- * Try to construct cross-platform clipboard data from selection data.
+ * Try to construct cross-platform clipboard data from selection data
+ * provided to us by Gtk+.
  *
  * @param[in] sd Gtk selection data to convert to CP clipboard data
+ *
+ * @return false on failure, true on success
  */
 
-void
-DnDUI::LocalGetSelection(const Gtk::SelectionData& sd) // IN
+bool
+DnDUI::SetCPClipboardFromGtk(const Gtk::SelectionData& sd) // IN
 {
    char *newPath;
    char *newRelPath;
@@ -1269,6 +1113,12 @@ DnDUI::LocalGetSelection(const Gtk::SelectionData& sd) // IN
        */
       utf::string source = sd.get_data_as_string().c_str();
       Debug("%s: Got file list: [%s]\n", __FUNCTION__, source.c_str());
+
+      if (sd.get_data_as_string().length() == 0) {
+         Debug("%s: empty file list!\n", __FUNCTION__);
+         return false;
+      }
+
       /*
        * In gnome, before file list there may be a extra line indicating it
        * is a copy or cut.
@@ -1313,7 +1163,7 @@ DnDUI::LocalGetSelection(const Gtk::SelectionData& sd) // IN
                               DynBuf_GetSize(&buf));
       }
       DynBuf_Destroy(&buf);
-      return;
+      return true;
    }
 
    /* Try to get plain text. */
@@ -1329,8 +1179,9 @@ DnDUI::LocalGetSelection(const Gtk::SelectionData& sd) // IN
          Debug("%s: Got text, size %"FMTSZ"u\n", __FUNCTION__, source.bytes());
       } else {
          Debug("%s: Failed to get text\n", __FUNCTION__);
+         return false;
       }
-      return;
+      return true;
    }
 
    /* Try to get RTF string. */
@@ -1342,10 +1193,13 @@ DnDUI::LocalGetSelection(const Gtk::SelectionData& sd) // IN
           CPClipboard_SetItem(&m_clipboard, CPFORMAT_RTF, source.c_str(),
                               source.bytes() + 1)) {
          Debug("%s: Got RTF, size %"FMTSZ"u\n", __FUNCTION__, source.bytes());
+         return true;
       } else {
          Debug("%s: Failed to get text\n", __FUNCTION__ );
+         return false;
       }
    }
+   return true;
 }
 
 
@@ -1452,10 +1306,10 @@ DnDUI::GetNextPath(utf::utf8string& str,
  */
 
 bool
-DnDUI::DnDHGFakeMove(const int x,
-                     const int y)
+DnDUI::SendFakeMouseMove(const int x,
+                         const int y)
 {
-   return DnDFakeXEvents(false, false, false, false, true, x, y);
+   return SendFakeXEvents(false, false, false, false, true, x, y);
 }
 
 
@@ -1475,17 +1329,20 @@ DnDUI::DnDHGFakeMove(const int x,
  * @param[in] xCoord           x coordinate
  * @param[in] yCoord           y coordinate
  *
+ * @note todo this code should be implemented using GDK APIs.
+ * @note todo this code should be moved into the detection window class
+ *
  * @return true on success, false on failure.
  */
 
 bool
-DnDUI::DnDFakeXEvents(const bool showWidget,
-                      const bool buttonEvent,
-                      const bool buttonPress,
-                      const bool moveWindow,
-                      const bool coordsProvided,
-                      const int xCoord,
-                      const int yCoord)
+DnDUI::SendFakeXEvents(const bool showWidget,
+                       const bool buttonEvent,
+                       const bool buttonPress,
+                       const bool moveWindow,
+                       const bool coordsProvided,
+                       const int xCoord,
+                       const int yCoord)
 {
    GtkWidget *widget;
    Window rootWnd;
@@ -1498,8 +1355,7 @@ DnDUI::DnDFakeXEvents(const bool showWidget,
    x = xCoord;
    y = yCoord;
 
-   Debug("%s: enter\n", __FUNCTION__);
-   widget = GetDetWndAsWidget(false);
+   widget = GetDetWndAsWidget();
 
    if (!widget) {
       Debug("%s: unable to get widget\n", __FUNCTION__);
@@ -1543,10 +1399,49 @@ DnDUI::DnDFakeXEvents(const bool showWidget,
          return false;
       }
 
-      Debug("%s: mouse is at (%d, %d)\n", __FUNCTION__, rootXReturn, rootYReturn);
+      Debug("%s: current mouse is at (%d, %d)\n", __FUNCTION__,
+            rootXReturn, rootYReturn);
+
+      /*
+       * Position away from the edge of the window.
+       */
+      int width = m_detWnd->GetScreenWidth();
+      int height = m_detWnd->GetScreenHeight();
+      bool change = false;
 
       x = rootXReturn;
       y = rootYReturn;
+
+      /*
+       * first do left and top edges.
+       */
+
+      if (x <= 5) {
+         x = 6;
+         change = true;
+      }
+
+      if (y <= 5) {
+         y = 6;
+         change = true;
+      }
+
+      /*
+       * next, move result away from right and bottom edges.
+       */
+      if (x > width - 5) {
+         x = width - 6;
+         change = true;
+      }
+      if (y > height - 5) {
+         y = height - 6;
+         change = true;
+      }
+
+      if (change) {
+         Debug("%s: adjusting mouse position. root %d, %d, adjusted %d, %d\n",
+               __FUNCTION__, rootXReturn, rootYReturn, x, y);
+      }
    }
 
    if (moveWindow) {
@@ -1557,8 +1452,9 @@ DnDUI::DnDFakeXEvents(const bool showWidget,
        * is okay since the window is invisible and hidden on cancels and DnD
        * finish.
        */
-      XMoveResizeWindow(dndXDisplay, dndXWindow, x, y, 25, 25);
+      XMoveResizeWindow(dndXDisplay, dndXWindow, x - 5 , y - 5, 25, 25);
       XRaiseWindow(dndXDisplay, dndXWindow);
+      Debug("%s: move wnd to (%d, %d, %d, %d)\n", __FUNCTION__, x - 5, y - 5 , x + 25, y + 25);
    }
 
    /*
@@ -1567,6 +1463,7 @@ DnDUI::DnDFakeXEvents(const bool showWidget,
     */
    XTestFakeMotionEvent(dndXDisplay, -1, x, y, CurrentTime);
    XTestFakeMotionEvent(dndXDisplay, -1, x + 1, y + 1, CurrentTime);
+   Debug("%s: move mouse to (%d, %d) and (%d, %d)\n", __FUNCTION__, x, y, x + 1, y + 1);
 
    if (buttonEvent) {
       Debug("%s: faking left mouse button %s\n", __FUNCTION__,
@@ -1587,30 +1484,20 @@ DnDUI::DnDFakeXEvents(const bool showWidget,
  * window. This function is also called by the code that issues fake
  * X events to the detection window.
  *
- * @param[in] full true to get the GtkWindow for the full (unity)
- * detection window, otherwise false.
- *
  * @return a pointer to the GtkWidget for the detection window, or NULL
  * on failure.
  */
 
 GtkWidget *
-DnDUI::GetDetWndAsWidget(const bool full)
+DnDUI::GetDetWndAsWidget()
 {
    GtkInvisible *window;
    GtkWidget *widget = NULL;
-   DragDetWnd *detWnd;
-
-   if (full) {
-      detWnd = m_detWndFull;
-   } else {
-      detWnd = m_detWnd;
-   }
 
-   if (!detWnd) {
+   if (!m_detWnd) {
       return NULL;
    }
-   window = detWnd->gobj();
+   window = m_detWnd->gobj();
    if (window) {
       widget = GTK_WIDGET(window);
    }
@@ -1627,6 +1514,7 @@ DnDUI::GetDetWndAsWidget(const bool full)
 void
 DnDUI::AddBlock()
 {
+   Debug("%s: enter\n", __FUNCTION__);
    if (m_blockAdded) {
       Debug("%s: block already added\n", __FUNCTION__);
       return;
@@ -1684,6 +1572,7 @@ DnDUI::ToDropEffect(Gdk::DragAction action)
 
    switch(action) {
    case Gdk::ACTION_COPY:
+   case Gdk::ACTION_DEFAULT:
       effect = DROP_COPY;
       break;
    case Gdk::ACTION_MOVE:
@@ -1693,7 +1582,6 @@ DnDUI::ToDropEffect(Gdk::DragAction action)
       effect = DROP_LINK;
       break;
    case Gdk::ACTION_PRIVATE:
-   case Gdk::ACTION_DEFAULT:
    case Gdk::ACTION_ASK:
    default:
       effect = DROP_UNKNOWN;
@@ -1703,4 +1591,273 @@ DnDUI::ToDropEffect(Gdk::DragAction action)
 }
 
 
+/**
+ *
+ * Try to extract file contents from m_clipboard. Write all files to a
+ * temporary staging directory. Construct uri list.
+ *
+ * @return true if success, false otherwise.
+ */
+
+bool
+DnDUI::WriteFileContentsToStagingDir(void)
+{
+   void *buf = NULL;
+   size_t sz = 0;
+   XDR xdrs;
+   CPFileContents fileContents;
+   CPFileContentsList *contentsList = NULL;
+   size_t nFiles = 0;
+   CPFileItem *fileItem = NULL;
+   Unicode tempDir = NULL;
+   size_t i = 0;
+   bool ret = false;
+
+   if (!CPClipboard_GetItem(&m_clipboard, CPFORMAT_FILECONTENTS, &buf, &sz)) {
+      return false;
+   }
+
+   /* Extract file contents from buf. */
+   xdrmem_create(&xdrs, (char *)buf, sz, XDR_DECODE);
+   memset(&fileContents, 0, sizeof fileContents);
+
+   if (!xdr_CPFileContents(&xdrs, &fileContents)) {
+      Debug("%s: xdr_CPFileContents failed.\n", __FUNCTION__);
+      xdr_destroy(&xdrs);
+      return false;
+   }
+   xdr_destroy(&xdrs);
+
+   contentsList = fileContents.CPFileContents_u.fileContentsV1;
+   if (!contentsList) {
+      Debug("%s: invalid contentsList.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   nFiles = contentsList->fileItem.fileItem_len;
+   if (0 == nFiles) {
+      Debug("%s: invalid nFiles.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   fileItem = contentsList->fileItem.fileItem_val;
+   if (!fileItem) {
+      Debug("%s: invalid fileItem.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   /*
+    * Write files into a temporary staging directory. These files will be moved
+    * to final destination, or deleted on next reboot.
+    */
+   tempDir = DnD_CreateStagingDirectory();
+   if (!tempDir) {
+      Debug("%s: DnD_CreateStagingDirectory failed.\n", __FUNCTION__);
+      goto exit;
+   }
+
+   m_HGFileContentsUriList = "";
+
+   for (i = 0; i < nFiles; i++) {
+      utf::string fileName;
+      utf::string filePathName;
+      VmTimeType createTime = -1;
+      VmTimeType accessTime = -1;
+      VmTimeType writeTime = -1;
+      VmTimeType attrChangeTime = -1;
+
+      if (!fileItem[i].cpName.cpName_val ||
+          0 == fileItem[i].cpName.cpName_len) {
+         Debug("%s: invalid fileItem[%"FMTSZ"u].cpName.\n", __FUNCTION__, i);
+         goto exit;
+      }
+
+      /*
+       * '\0' is used as directory separator in cross-platform name. Now turn
+       * '\0' in data into DIRSEPC.
+       *
+       * Note that we don't convert the final '\0' into DIRSEPC so the string
+       * is NUL terminated.
+       */
+      CPNameUtil_CharReplace(fileItem[i].cpName.cpName_val,
+                             fileItem[i].cpName.cpName_len - 1,
+                             '\0',
+                             DIRSEPC);
+      fileName = fileItem[i].cpName.cpName_val;
+      filePathName = tempDir;
+      filePathName += DIRSEPS + fileName;
+
+      if (fileItem[i].validFlags & CP_FILE_VALID_TYPE &&
+          CP_FILE_TYPE_DIRECTORY == fileItem[i].type) {
+         if (!File_CreateDirectory(filePathName.c_str())) {
+            goto exit;
+         }
+         Debug("%s: created directory [%s].\n",
+               __FUNCTION__, filePathName.c_str());
+      } else if (fileItem[i].validFlags & CP_FILE_VALID_TYPE &&
+                 CP_FILE_TYPE_REGULAR == fileItem[i].type) {
+         FileIODescriptor file;
+         FileIOResult fileErr;
+
+         FileIO_Invalidate(&file);
+
+         fileErr = FileIO_Open(&file,
+                               filePathName.c_str(),
+                               FILEIO_ACCESS_WRITE,
+                               FILEIO_OPEN_CREATE_EMPTY);
+         if (!FileIO_IsSuccess(fileErr)) {
+            goto exit;
+         }
+
+         fileErr = FileIO_Write(&file,
+                                fileItem[i].content.content_val,
+                                fileItem[i].content.content_len,
+                                NULL);
+
+         FileIO_Close(&file);
+         Debug("%s: created file [%s].\n",
+               __FUNCTION__, filePathName.c_str());
+      } else {
+         /*
+          * Right now only Windows can provide CPFORMAT_FILECONTENTS data.
+          * Symlink file is not expected. Continue with next file if the
+          * type is not valid.
+          */
+         continue;
+      }
+
+      /* Update file time attributes. */
+      createTime = fileItem->validFlags & CP_FILE_VALID_CREATE_TIME ?
+         fileItem->createTime: -1;
+      accessTime = fileItem->validFlags & CP_FILE_VALID_ACCESS_TIME ?
+         fileItem->accessTime: -1;
+      writeTime = fileItem->validFlags & CP_FILE_VALID_WRITE_TIME ?
+         fileItem->writeTime: -1;
+      attrChangeTime = fileItem->validFlags & CP_FILE_VALID_CHANGE_TIME ?
+         fileItem->attrChangeTime: -1;
+
+      if (!File_SetTimes(filePathName.c_str(),
+                         createTime,
+                         accessTime,
+                         writeTime,
+                         attrChangeTime)) {
+         /* Not a critical error, only log it. */
+         Debug("%s: File_SetTimes failed with file [%s].\n",
+               __FUNCTION__, filePathName.c_str());
+      }
+
+      /* Update file permission attributes. */
+      if (fileItem->validFlags & CP_FILE_VALID_PERMS) {
+         if (Posix_Chmod(filePathName.c_str(),
+                         fileItem->permissions) < 0) {
+            /* Not a critical error, only log it. */
+            Debug("%s: Posix_Chmod failed with file [%s].\n",
+                  __FUNCTION__, filePathName.c_str());
+         }
+      }
+
+      /*
+       * If there is no DIRSEPC inside the fileName, this file/directory is a
+       * top level one. We only put top level name into uri list.
+       */
+      if (fileName.find(DIRSEPS, 0) == utf::string::npos) {
+         m_HGFileContentsUriList += "file://" + filePathName + "\r\n";
+      }
+   }
+   Debug("%s: created uri list [%s].\n",
+         __FUNCTION__, m_HGFileContentsUriList.c_str());
+   ret = true;
+
+exit:
+   xdr_free((xdrproc_t) xdr_CPFileContents, (char *)&fileContents);
+   if (tempDir && !ret) {
+      DnD_DeleteStagingFiles(tempDir, false);
+   }
+   free(tempDir);
+   return ret;
+}
+
+
+/**
+ *
+ * Tell host that we are done with HG DnD initialization.
+ */
+
+void
+DnDUI::SourceDragStartDone(void)
+{
+   Debug("%s: enter\n", __FUNCTION__);
+   m_inHGDrag = true;
+   m_DnD->HGDragStartDone();
+}
+
+
+/**
+ * Set block control member.
+ *
+ * @param[in] block control as setup by vmware-user.
+ */
+
+void
+DnDUI::SetBlockControl(DnDBlockControl *blockCtrl)
+{
+   m_blockCtrl = blockCtrl;
+}
+
+
+/**
+ *
+ * Got feedback from our DropSource, send it over to host. Called by
+ * drag motion callback.
+ *
+ * @param[in] effect feedback to send to the UI-independent DnD layer.
+ */
+
+void
+DnDUI::SourceUpdateFeedback(DND_DROPEFFECT effect)
+{
+   Debug("%s: entering\n", __FUNCTION__);
+   m_DnD->SetFeedback(effect);
+}
+
+
+/**
+ *
+ * This is triggered when user drags valid data from guest to host. Try to
+ * get clip data and notify host to start GH DnD.
+ */
 
+void
+DnDUI::TargetDragEnter(void)
+{
+   Debug("%s: entering\n", __FUNCTION__);
+
+   /* Check if there is valid data with current detection window. */
+   if (!CPClipboard_IsEmpty(&m_clipboard)) {
+      Debug("%s: got valid data from detWnd.\n", __FUNCTION__);
+      m_DnD->DragEnter(&m_clipboard);
+   }
+
+   /*
+    * Show the window, and position it under the current mouse position.
+    * This is particularly important for KDE 3.5 guests.
+    */
+   SendFakeXEvents(true, false, true, true, false, 0, 0);
+}
+
+
+/**
+ *
+ * Get Unix time in milliseconds. See man 2 gettimeofday for details.
+ *
+ * @return unix time in milliseconds.
+ */
+
+unsigned long
+DnDUI::GetTimeInMillis(void)
+{
+   VmTimeType atime;
+
+   Hostinfo_GetTimeOfDay(&atime);
+   return((unsigned long)(atime / 1000));
+}
index b09fb5d3c93e7b945bedd63dbe7a51da4aa9da51..233086c257bd7fbfbe6f79c66de8b3a2ed36f431 100644 (file)
@@ -58,123 +58,135 @@ class DnDUI
 public:
    DnDUI(DblLnkLst_Links *eventQueue);
    ~DnDUI();
-   void Init();
+   bool Init();
    void VmxDnDVersionChanged(struct RpcIn *rpcIn,
                              uint32 version)
-      { ASSERT(m_DnD); m_DnD->VmxDnDVersionChanged(rpcIn, version); }
+      {ASSERT(m_DnD); m_DnD->VmxDnDVersionChanged(rpcIn, version);}
    void SetDnDAllowed(bool isDnDAllowed)
-      { ASSERT(m_DnD); m_DnD->SetDnDAllowed(isDnDAllowed); }
-   void Reset(void);
-   void ResetUIStateCB();
+      {ASSERT(m_DnD); m_DnD->SetDnDAllowed(isDnDAllowed);}
    void SetBlockControl(DnDBlockControl *blockCtrl);
    void SetUnityMode(Bool mode)
       {m_unityMode = mode;};
-   DragDetWnd *GetFullDetWnd() {return m_detWndFull;}
-   GtkWidget *GetDetWndAsWidget(const bool full);
+
+   DragDetWnd *GetFullDetWnd() {return m_detWnd;}
+   GtkWidget *GetDetWndAsWidget();
+
+private:
 
    /**
-    * Source functions for HG DnD
+    * Blocking FS Helper Functions.
     */
-   void SourceDragStartDone(void);
-   void SourceUpdateFeedback(DND_DROPEFFECT effect);
+   void AddBlock();
+   void RemoveBlock();
 
    /**
-    * Target function for GH DnD.
+    * Callbacks from Common DnD layer.
     */
-   void TargetDragEnter(void);
+   void CommonResetCB();
+   void CommonUpdateMouseCB(int32 x, int32 y);
 
    /**
-    * Callbacks. H->G
+    * Source functions for HG DnD.
     */
+   void CommonDragStartCB(const CPClipboard *clip, std::string stagingDir);
+   void CommonSourceDropCB(void);
 
-   bool LocalDragMotionCB(const Glib::RefPtr<Gdk::DragContext> &dc, int x,
-                          int y, guint time);
-   void LocalDragDataReceivedCB(const Glib::RefPtr<Gdk::DragContext> &dc,
-                                int x, int y, const Gtk::SelectionData &sd,
-                                guint info, guint time);
-   void LocalGetSelection(const Gtk::SelectionData& sd);
-   void LocalDragLeaveCB(const Glib::RefPtr<Gdk::DragContext> &dc, guint time);
-   bool LocalDragDropCB(const Glib::RefPtr<Gdk::DragContext> &dc, int x, int y,
-                        guint time);
-
-   void SourceFeedbackChangedCB(DND_DROPEFFECT effect, const Glib::RefPtr<Gdk::DragContext> dc);
-
-   void LocalDragDataGetCB(
-      const Glib::RefPtr<Gdk::DragContext>& context,
-      Gtk::SelectionData& selection_data, guint info, guint time);
-   void LocalDragEndCB(
-      const Glib::RefPtr<Gdk::DragContext>& context);
-   void LocalDragBeginCB(
-      const Glib::RefPtr<Gdk::DragContext>& context);
-
-#if defined(DETWNDTEST)
-   void CreateTestUI();
-#endif
-private:
+   /**
+    * Called when HG Dnd is completed.
+    */
+   void CommonSourceCancelCB(void);
 
-   void AddBlock();
-   void RemoveBlock();
+   /**
+    * Called when GH DnD is completed.
+    */
+   void CommonDestPrivateDropCB(int32 x, int32 y);
+   void CommonDestCancelCB(void);
 
    /**
-    * Source functions for HG DnD.
+    * Source functions for file transfer.
+    */
+   void CommonSourceFileCopyDoneCB(bool success, std::vector<uint8> stagingDir);
+
+   /**
+    * Callbacks for showing/hiding detection window.
+    */
+   void CommonUpdateDetWndCB(bool bShow, int32 x, int32 y);
+   void CommonUpdateUnityDetWndCB(bool bShow, uint32 unityWndId, bool bottom);
+   void CommonMoveDetWndToMousePos(void);
+
+   /**
+    * Gtk+ Callbacks: Drag Destination.
     */
-   void RemoteDragStartCB(const CPClipboard *clip,
-                          std::string stagingDir);
-   void SourceDropCB(void);
-   void SourceCancelCB(void);
+   void GtkDestDragDataReceivedCB(const Glib::RefPtr<Gdk::DragContext> &dc,
+                                  int x, int y, const Gtk::SelectionData &sd,
+                                  guint info, guint time);
+   bool GtkDestDragDropCB(const Glib::RefPtr<Gdk::DragContext> &dc,
+                          int x, int y, guint time);
+   void GtkDestDragLeaveCB(const Glib::RefPtr<Gdk::DragContext> &dc,
+                           guint time);
+   bool GtkDestDragMotionCB(const Glib::RefPtr<Gdk::DragContext> &dc, int x,
+                            int y, guint time);
 
    /**
-    * Called when GH is completed.
+    * Gtk+ Callbacks: Drag Source.
+    */
+   void GtkSourceDragBeginCB(const Glib::RefPtr<Gdk::DragContext>& context);
+   void GtkSourceDragDataGetCB(const Glib::RefPtr<Gdk::DragContext>& context,
+                               Gtk::SelectionData& selection_data, guint info,
+                               guint time);
+   void GtkSourceDragEndCB(const Glib::RefPtr<Gdk::DragContext>& context);
+   /**
+    * Source functions for HG DnD. Makes calls to common layer.
     */
-   void GHCancelCB(void);
+   void SourceDragStartDone(void);
+   void SourceUpdateFeedback(DND_DROPEFFECT effect);
 
    /**
-    * Source functions for HG file transfer.
+    * Target function for GH DnD. Makes call to common layer.
     */
-   void GetLocalFilesDoneCB(bool success, std::vector<uint8> stagingDir);
+   void TargetDragEnter(void);
 
    /**
     * Misc methods.
     */
+   bool SetCPClipboardFromGtk(const Gtk::SelectionData& sd);
    std::string GetLastDirName(const std::string &str);
    utf::utf8string GetNextPath(utf::utf8string &str, size_t& index);
-   void UpdateDetWndCB(bool bShow, int32 x, int32 y);
-   void UpdateUnityDetWndCB(bool bShow, uint32 unityWndId);
    DND_DROPEFFECT ToDropEffect(Gdk::DragAction action);
    void SetTargetsAndCallbacks();
-   bool DnDFakeXEvents(const bool showWidget, const bool buttonEvent,
-      const bool buttonPress, const bool moveWindow,
-      const bool coordsProvided, const int xCoord, const int yCoord);
-   bool DnDHGFakeMove(const int x, const int y);
-   bool LocalPrepareFileContentsDrag();
+   bool SendFakeXEvents(const bool showWidget, const bool buttonEvent,
+                        const bool buttonPress, const bool moveWindow,
+                        const bool coordsProvided,
+                        const int xCoord, const int yCoord);
+   bool SendFakeMouseMove(const int x, const int y);
+   bool WriteFileContentsToStagingDir();
+   unsigned long GetTimeInMillis();
 
    DblLnkLst_Links *m_eventQueue;
    DnD *m_DnD;
    std::string m_HGStagingDir;
    utf::string m_HGFileContentsUriList;
    DragDetWnd *m_detWnd;
-   DragDetWnd *m_detWndFull;
    CPClipboard m_clipboard;
    DnDBlockControl *m_blockCtrl;
    bool m_HGGetDataInProgress;
    int m_HGEffect;
    bool m_blockAdded;
 
-   /* State to determine if drag motion is is a drag enter. */
+   /* State to determine if drag motion is a drag enter. */
    bool m_GHDnDInProgress;
    /* Icon updates from the guest. */
-   bool m_GHDnDHostStatus;
-   /* Drop actions for host and guest respectively. */
-   Gdk::DragAction m_GHDnDAction;
    /* Only update mouse when we have clipboard contents from the host. */
    bool m_GHDnDDataReceived;
    bool m_GHDnDDropOccurred;
-   bool m_VMIsSource;
-   sigc::connection m_feedbackChanged;
    bool m_unityMode;
    bool m_inHGDrag;
    DND_DROPEFFECT m_effect;
    bool m_isFileDnD;
+   int32 m_mousePosX;
+   int32 m_mousePosY;
+   GdkDragContext *m_dc;
+   unsigned long m_destDropTime;
 };
 
 #endif // DND_UI_H
index 6c7b3be43c04f0dc5a0089dac9c414db747f6362..25f32c3f90695786bd39636f60bf7cc4ed00d7ba 100644 (file)
@@ -42,8 +42,12 @@ extern "C" {
  * Constructor.
  */
 
-DragDetWnd::DragDetWnd()
+DragDetWnd::DragDetWnd() :
+   m_isVisible(false)
 {
+#if defined(DETWNDDEBUG)
+   DebugSetAttributes();
+#endif
 }
 
 
index 55dba43c14326363ba1b5e6fdcd0e39fd4fb5441..6ee455f45de6e1f1d9996a9c3e68ca23cff9b9a7 100644 (file)
@@ -50,11 +50,14 @@ public:
    void SetGeometry(const int x, const int y,
                     const int width, const int height);
    void GetGeometry(int &x, int &y, int &width, int &height);
+   void SetIsVisible(const bool isVisible) {m_isVisible = isVisible;};
+   bool GetIsVisible() {return m_isVisible;};
 #if defined(DETWNDEBUG)
-   void SetAttributes();
+   void DebugSetAttributes();
 #endif
 private:
    void Flush();
+   bool m_isVisible;
 };
 
 #if defined(DETWNDTEST)
index 1f8862a1948723c75e60bbc683e35606d70d04d1..87a697ad2dbd8941eb210fda365d15540fcbf0b2 100644 (file)
@@ -543,7 +543,7 @@ VMwareUserRpcInSetOptionCB(char const **result,     // OUT
    char *value;
    unsigned int index = 0;
    Bool ret = FALSE;
-   char *retStr = NULL;
+   const char *retStr = NULL;
 
    /* parse the option & value string */
    option = StrUtil_GetNextToken(&index, args, " ");