~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to lib/hgfsServer/hgfsServer.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 *
17
17
 *********************************************************/
18
18
 
 
19
#if defined(__APPLE__)
 
20
/*
 
21
 * DirectoryEntry type that is used in common code is
 
22
 * defined as dirent for Mac OS.
 
23
 * _DARWIN_USE_64_BIT_INODE definition is needed to make dirent
 
24
 * structure definitions in this file and in HgfsServerLinux.c
 
25
 * consistent.
 
26
 */
 
27
#define _DARWIN_USE_64_BIT_INODE
 
28
#endif
 
29
 
19
30
#include <string.h>
20
31
#include <stdlib.h>
21
32
 
33
44
#include "file.h"
34
45
#include "util.h"
35
46
#include "wiper.h"
 
47
#include "hgfsServer.h"
36
48
#include "hgfsDirNotify.h"
37
49
#include "hgfsTransport.h"
38
50
#include "userlock.h"
39
51
#include "poll.h"
40
 
#include "libMutexRank.h"
 
52
#include "mutexRankLib.h"
41
53
#include "vm_basic_asm.h"
 
54
#include "unicodeOperations.h"
42
55
 
43
56
#if defined(_WIN32)
44
57
#include <io.h>
95
108
#define HGFS_ASSERT_MINIMUM_OP(op)
96
109
#endif
97
110
 
 
111
#ifdef VMX86_TOOLS
 
112
#define Config_GetBool(defaultValue,fmt) (defaultValue)
 
113
#endif
98
114
 
99
115
/*
100
116
 * This ensures that the hgfs name conversion code never fails on long
116
132
/* Default maximun number of open nodes that have server locks. */
117
133
#define MAX_LOCKED_FILENODES 10
118
134
 
119
 
 
120
135
/* Maximum number of cached open nodes. */
121
136
static unsigned int maxCachedOpenNodes;
122
137
 
129
144
 */
130
145
static Atomic_uint32 hgfsHandleCounter = {0};
131
146
 
 
147
/*
 
148
 * Number of outstanding asynchronous operations.
 
149
 */
 
150
static Atomic_uint32 gHgfsAsyncCounter = {0};
 
151
static MXUserExclLock *gHgfsAsyncLock;
 
152
static MXUserCondVar  *gHgfsAsyncVar;
132
153
 
133
154
static HgfsServerStateLogger *hgfsMgrData = NULL;
134
155
 
154
175
 * if the close session is called from the channel.
155
176
 */
156
177
 
157
 
#ifdef VMX86_TOOLS
158
 
/* We need to have a static session for use of HGFS server inside Tools. */
159
 
struct HgfsStaticSession {
160
 
   HgfsSessionInfo *session;        /* Session. */
161
 
   char *bufferOut;                 /* Reply buffer. */
162
 
   size_t bufferOutLen;             /* Reply buffer length. */
163
 
} hgfsStaticSession;
164
 
#endif
165
 
 
166
178
/* Session related callbacks. */
167
179
static void HgfsServerSessionReceive(HgfsPacket *packet,
168
180
                                     void *clientData);
169
181
static Bool HgfsServerSessionConnect(void *transportData,
170
182
                                     HgfsServerChannelCallbacks *channelCbTable,
 
183
                                     uint32 channelCapabililies,
171
184
                                     void **clientData);
172
185
static void HgfsServerSessionDisconnect(void *clientData);
173
186
static void HgfsServerSessionClose(void *clientData);
187
200
   HgfsServerSessionSendComplete,
188
201
};
189
202
 
190
 
static Bool hgfsChangeNotificationSupported = FALSE;
 
203
/* Lock that protects shared folders list. */
 
204
static MXUserExclLock *gHgfsSharedFoldersLock = NULL;
 
205
 
 
206
/* List of shared folders nodes. */
 
207
static DblLnkLst_Links gHgfsSharedFoldersList;
 
208
 
 
209
static Bool gHgfsInitialized = FALSE;
 
210
 
 
211
/*
 
212
 * Number of active sessions that support change directory notification. HGFS server
 
213
 * needs to maintain up-to-date shared folders list when there is
 
214
 * at least one such session.
 
215
 */
 
216
static Bool gHgfsDirNotifyActive = FALSE;
 
217
 
 
218
typedef struct HgfsSharedFolderProperties {
 
219
   DblLnkLst_Links links;
 
220
   char *name;                                /* Name of the share. */
 
221
   HgfsSharedFolderHandle notificationHandle; /* Directory notification handle. */
 
222
   Bool markedForDeletion;
 
223
} HgfsSharedFolderProperties;
191
224
 
192
225
/*
193
226
 *    Limit payload to 16M + header.
242
275
static void HgfsServerCompleteRequest(HgfsInternalStatus status,
243
276
                                      size_t replyPayloadSize,
244
277
                                      HgfsInputParam *input);
 
278
static Bool HgfsHandle2NotifyInfo(HgfsHandle handle,
 
279
                                  HgfsSessionInfo *session,
 
280
                                  char **fileName,
 
281
                                  size_t *fileNameSize,
 
282
                                  HgfsSharedFolderHandle *folderHandle);
 
283
static void Hgfs_NotificationCallback(HgfsSharedFolderHandle sharedFolder,
 
284
                                      HgfsSubscriberHandle subscriber,
 
285
                                      char* fileName,
 
286
                                      uint32 mask,
 
287
                                      struct HgfsSessionInfo *session);
245
288
 
246
289
/*
247
290
 * Opcode handlers
266
309
static void HgfsServerDestroySession(HgfsInputParam *input);
267
310
static void HgfsServerClose(HgfsInputParam *input);
268
311
static void HgfsServerSearchClose(HgfsInputParam *input);
 
312
static void HgfsServerSetDirNotifyWatch(HgfsInputParam *input);
 
313
static void HgfsServerRemoveDirNotifyWatch(HgfsInputParam *input);
269
314
 
270
315
 
271
316
/*
408
453
 *
409
454
 *    Retrieve the file node a handle refers to.
410
455
 *
411
 
 *    The session's nodeArrayLock should be acquired prior to calling this function.
 
456
 *    The session's nodeArrayLock should be acquired prior to calling this
 
457
 *    function.
412
458
 *
413
459
 * Results:
414
460
 *    The file node if the handle is valid (i.e. it refers to an existing file
451
497
 *
452
498
 *    Retrieve the handle that represents a file node outside of the server.
453
499
 *
454
 
 *    The session's nodeArrayLock should be acquired prior to calling this function.
 
500
 *    The session's nodeArrayLock should be acquired prior to calling this
 
501
 *    function.
455
502
 *
456
503
 * Results:
457
504
 *    The handle
478
525
 *
479
526
 *    Debugging routine; print all nodes in the nodeArray.
480
527
 *
481
 
 *    The session's nodeArrayLock should be acquired prior to calling this function.
 
528
 *    The session's nodeArrayLock should be acquired prior to calling this
 
529
 *    function.
482
530
 *
483
531
 * Results:
484
532
 *    None
818
866
                                  fileNameSize);
819
867
}
820
868
 
 
869
 
821
870
/*
822
871
 *-----------------------------------------------------------------------------
823
872
 *
884
933
/*
885
934
 *-----------------------------------------------------------------------------
886
935
 *
 
936
 * HgfsHandle2FileNameMode --
 
937
 *
 
938
 *    Given an OS handle/fd, return information needed for directory
 
939
 *    notification package: relative to the root share file name and
 
940
 *    shared folder notification handle.
 
941
 *
 
942
 * Results:
 
943
 *    TRUE if the node was found.
 
944
 *    FALSE otherwise.
 
945
 *
 
946
 * Side effects:
 
947
 *    None.
 
948
 *
 
949
 *-----------------------------------------------------------------------------
 
950
 */
 
951
 
 
952
Bool
 
953
HgfsHandle2NotifyInfo(HgfsHandle handle,                    // IN: Hgfs file handle
 
954
                      HgfsSessionInfo *session,             // IN: Session info
 
955
                      char **fileName,                      // OUT: UTF8 file name
 
956
                      size_t *fileNameSize,                 // OUT: UTF8 file name size
 
957
                      HgfsSharedFolderHandle *folderHandle) // OUT: shared folder handle
 
958
{
 
959
   Bool found = FALSE;
 
960
   HgfsFileNode *existingFileNode;
 
961
   char *name;
 
962
   size_t nameSize;
 
963
 
 
964
   ASSERT(fileName != NULL && fileNameSize != NULL);
 
965
   MXUser_AcquireExclLock(session->nodeArrayLock);
 
966
 
 
967
   existingFileNode = HgfsHandle2FileNode(handle, session);
 
968
   if (NULL != existingFileNode) {
 
969
      nameSize = existingFileNode->utf8NameLen - existingFileNode->shareInfo.rootDirLen;
 
970
      name = Util_SafeMalloc(nameSize + 1);
 
971
      *folderHandle = existingFileNode->shareInfo.handle;
 
972
      memcpy(name, existingFileNode->utf8Name, nameSize);
 
973
      name[nameSize] = '\0';
 
974
      *fileName = name;
 
975
      *fileNameSize = nameSize;
 
976
      found = TRUE;
 
977
   }
 
978
 
 
979
   MXUser_ReleaseExclLock(session->nodeArrayLock);
 
980
 
 
981
   return found;
 
982
}
 
983
 
 
984
 
 
985
/*
 
986
 *-----------------------------------------------------------------------------
 
987
 *
887
988
 * HgfsFileHasServerLock --
888
989
 *
889
990
 *    Check if the file with the given name is already opened with a server
918
1019
 
919
1020
   for (i = 0; i < session->numNodes; i++) {
920
1021
      HgfsFileNode *existingFileNode = &session->nodeArray[i];
 
1022
 
921
1023
      if ((existingFileNode->state == FILENODE_STATE_IN_USE_CACHED) &&
922
1024
          (existingFileNode->serverLock != HGFS_LOCK_NONE) &&
923
1025
          (!stricmp(existingFileNode->utf8Name, utf8Name))) {
1353
1455
 *    initializes it appropriately, adds the new entries to the
1354
1456
 *    free list, and then returns one off the free list.
1355
1457
 *
1356
 
 *    The session's nodeArrayLock should be acquired prior to calling this function.
 
1458
 *    The session's nodeArrayLock should be acquired prior to calling this
 
1459
 *    function.
1357
1460
 *
1358
1461
 * Results:
1359
1462
 *    An unused file node on success
1526
1629
 *
1527
1630
 *    Free its localname, clear its fields, return it to the free list.
1528
1631
 *
1529
 
 *    The session's nodeArrayLock should be acquired prior to calling this function.
 
1632
 *    The session's nodeArrayLock should be acquired prior to calling this
 
1633
 *    function.
1530
1634
 *
1531
1635
 * Results:
1532
1636
 *    None
1686
1790
   newNode->state = FILENODE_STATE_IN_USE_NOT_CACHED;
1687
1791
   newNode->shareInfo.readPermissions = openInfo->shareInfo.readPermissions;
1688
1792
   newNode->shareInfo.writePermissions = openInfo->shareInfo.writePermissions;
 
1793
   newNode->shareInfo.handle = openInfo->shareInfo.handle;
1689
1794
 
1690
1795
   LOG(4, ("%s: got new node, handle %u\n", __FUNCTION__,
1691
1796
           HgfsFileNode2Handle(newNode)));
1807
1912
      DblLnkLst_Unlink1(&node->links);
1808
1913
      node->state = FILENODE_STATE_IN_USE_NOT_CACHED;
1809
1914
      session->numCachedOpenNodes--;
1810
 
      LOG(4, ("%s: cache entries %u remove node %s id %"FMT64"u fd %u .\n", __FUNCTION__,
1811
 
              session->numCachedOpenNodes, node->utf8Name,
 
1915
      LOG(4, ("%s: cache entries %u remove node %s id %"FMT64"u fd %u .\n",
 
1916
              __FUNCTION__, session->numCachedOpenNodes, node->utf8Name,
1812
1917
              node->localId.fileId, node->fileDesc));
1813
1918
 
1814
1919
      /*
1852
1957
 *    the cache then move it to the end of the list. Most recently
1853
1958
 *    used nodes move towards the end of the list.
1854
1959
 *
1855
 
 *    The session nodeArrayLock should be acquired prior to calling this function.
 
1960
 *    The session nodeArrayLock should be acquired prior to calling this
 
1961
 *    function.
1856
1962
 *
1857
1963
 * Results:
1858
1964
 *    TRUE if the node is found in the cache.
2089
2195
/*
2090
2196
 *-----------------------------------------------------------------------------
2091
2197
 *
 
2198
 * HgfsSearchIsBaseNameSpace --
 
2199
 *
 
2200
 *    Check if the search is the base of our name space, i.e. the dirents are
 
2201
 *    the shares themselves.
 
2202
 *
 
2203
 * Results:
 
2204
 *    TRUE if the search is the base of the name space, FALSE otherwise.
 
2205
 *
 
2206
 * Side effects:
 
2207
 *    None
 
2208
 *
 
2209
 *-----------------------------------------------------------------------------
 
2210
 */
 
2211
 
 
2212
static Bool
 
2213
HgfsSearchIsBaseNameSpace(HgfsSearch const *search) // IN
 
2214
{
 
2215
   ASSERT(search);
 
2216
 
 
2217
   return search->type == DIRECTORY_SEARCH_TYPE_BASE;
 
2218
}
 
2219
 
 
2220
 
 
2221
/*
 
2222
 *-----------------------------------------------------------------------------
 
2223
 *
2092
2224
 * HgfsGetSearchCopy --
2093
2225
 *
2094
2226
 *    Make a copy of the search. It should not be kept around for long, as the
2200
2332
   newSearch->handle = HgfsServerGetNextHandleCounter();
2201
2333
 
2202
2334
   newSearch->utf8DirLen = strlen(utf8Dir);
2203
 
   newSearch->utf8Dir = strdup(utf8Dir);
2204
 
   if (newSearch->utf8Dir == NULL) {
2205
 
      HgfsRemoveSearchInternal(newSearch, session);
2206
 
 
2207
 
      return NULL;
2208
 
   }
 
2335
   newSearch->utf8Dir = Util_SafeStrdup(utf8Dir);
2209
2336
 
2210
2337
   newSearch->utf8ShareNameLen = strlen(utf8ShareName);
2211
 
   newSearch->utf8ShareName = strdup(utf8ShareName);
2212
 
   if (newSearch->utf8ShareName == NULL) {
2213
 
      HgfsRemoveSearchInternal(newSearch, session);
2214
 
 
2215
 
      return NULL;
2216
 
   }
 
2338
   newSearch->utf8ShareName = Util_SafeStrdup(utf8ShareName);
2217
2339
 
2218
2340
   newSearch->shareInfo.rootDirLen = strlen(rootDir);
2219
 
   newSearch->shareInfo.rootDir = strdup(rootDir);
2220
 
   if (newSearch->shareInfo.rootDir == NULL) {
2221
 
      HgfsRemoveSearchInternal(newSearch, session);
2222
 
      return NULL;
2223
 
   }
 
2341
   newSearch->shareInfo.rootDir = Util_SafeStrdup(rootDir);
2224
2342
 
2225
2343
   LOG(4, ("%s: got new search, handle %u\n", __FUNCTION__,
2226
2344
           HgfsSearch2SearchHandle(newSearch)));
2378
2496
 
2379
2497
      nameLen = strlen(originalDent->d_name);
2380
2498
      /*
2381
 
       * Make sure the name will not overrun the d_name buffer, the end of which
2382
 
       * is also the end of the DirectoryEntry.
 
2499
       * Make sure the name will not overrun the d_name buffer, the end of
 
2500
       * which is also the end of the DirectoryEntry.
2383
2501
       */
2384
2502
      ASSERT(offsetof(DirectoryEntry, d_name) + nameLen < originalDent->d_reclen);
2385
2503
 
2539
2657
 
2540
2658
   HGFS_ASSERT_INPUT(input);
2541
2659
 
2542
 
   if (HgfsUnpackCloseRequest(input->payload, input->payloadSize, input->op, &file)) {
2543
 
 
 
2660
   if (HgfsUnpackCloseRequest(input->payload, input->payloadSize,
 
2661
                              input->op, &file)) {
2544
2662
      LOG(4, ("%s: close fh %u\n", __FUNCTION__, file));
2545
2663
 
2546
2664
      if (!HgfsRemoveFromCache(file, input->session)) {
2587
2705
 
2588
2706
   HGFS_ASSERT_INPUT(input);
2589
2707
 
2590
 
   if (HgfsUnpackSearchCloseRequest(input->payload, input->payloadSize, input->op,
2591
 
                                    &search)) {
2592
 
 
 
2708
   if (HgfsUnpackSearchCloseRequest(input->payload, input->payloadSize,
 
2709
                                    input->op, &search)) {
2593
2710
      LOG(4, ("%s: close search #%u\n", __FUNCTION__, search));
2594
2711
 
2595
2712
      if (HgfsRemoveSearch(search, input->session)) {
2596
 
         if (HgfsPackSearchCloseReply(input->packet, input->metaPacket, input->op,
 
2713
         if (HgfsPackSearchCloseReply(input->packet, input->metaPacket,
 
2714
                                      input->op,
2597
2715
                                      &replyPayloadSize, input->session)) {
2598
2716
            status = HGFS_ERROR_SUCCESS;
2599
2717
         } else {
2676
2794
   { HgfsServerDestroySession,   offsetof(HgfsRequestDestroySessionV4, reserved),  REQ_SYNC},
2677
2795
   { HgfsServerRead,             sizeof (HgfsRequestReadV3),                       REQ_SYNC},
2678
2796
   { HgfsServerWrite,            sizeof (HgfsRequestWriteV3),                      REQ_SYNC},
 
2797
   { HgfsServerSetDirNotifyWatch,    sizeof (HgfsRequestSetWatchV4),               REQ_SYNC},
 
2798
   { HgfsServerRemoveDirNotifyWatch, sizeof (HgfsRequestRemoveWatchV4),            REQ_SYNC},
2679
2799
 
2680
2800
};
2681
2801
 
2714
2834
      HgfsHeader *header;
2715
2835
      replySize = sizeof *header + replyPayloadSize;
2716
2836
      replyPacketSize = replySize;
2717
 
      header = HSPU_GetReplyPacket(input->packet, &replyPacketSize, input->session);
 
2837
      header = HSPU_GetReplyPacket(input->packet, &replyPacketSize,
 
2838
                                   input->session);
2718
2839
      packetOut = (char *)header;
2719
2840
 
2720
2841
      ASSERT_DEVEL(header && (replySize <= replyPacketSize));
2724
2845
      }
2725
2846
   } else {
2726
2847
      HgfsReply *reply;
2727
 
      replySize = sizeof *reply + replyPayloadSize;
 
2848
 
 
2849
      /*
 
2850
       * Starting from HGFS V3 header is not included in the payload size.
 
2851
       */
 
2852
      if (input->op < HGFS_OP_OPEN_V3) {
 
2853
         replySize = MAX(replyPayloadSize, sizeof *reply);
 
2854
      } else {
 
2855
         replySize = sizeof *reply + replyPayloadSize;
 
2856
      }
2728
2857
      replyPacketSize = replySize;
2729
 
      reply = HSPU_GetReplyPacket(input->packet, &replyPacketSize, input->session);
 
2858
      reply = HSPU_GetReplyPacket(input->packet, &replyPacketSize,
 
2859
                                  input->session);
2730
2860
      packetOut = (char *)reply;
2731
2861
 
2732
2862
      ASSERT_DEVEL(reply && (replySize <= replyPacketSize));
2735
2865
         reply->status = HgfsConvertFromInternalStatus(status);
2736
2866
      }
2737
2867
   }
2738
 
   if (!HgfsPacketSend(input->packet, packetOut, replySize, input->session, 0)) {
 
2868
   if (!HgfsPacketSend(input->packet, packetOut, replySize,
 
2869
                       input->session, 0)) {
2739
2870
      /* Send failed. Drop the reply. */
2740
2871
      LOG(4, ("Error sending reply\n"));
2741
2872
   }
2770
2901
                                             &input->metaPacketSize,
2771
2902
                                             input->session);
2772
2903
   }
 
2904
 
 
2905
   input->payload = (char *)input->metaPacket + input->payloadOffset;
2773
2906
   (*handlers[input->op].handler)(input);
2774
2907
}
2775
2908
 
2784
2917
 *    This function cannot fail; if something goes wrong, it returns
2785
2918
 *    a packet containing only a reply header with error code.
2786
2919
 *
2787
 
 *    The handler function can send the reply packet either using HgfsPacketSend
2788
 
 *    helper functions. This function would return error
 
2920
 *    The handler function can send the reply packet either using
 
2921
 *    HgfsPacketSend helper functions. This function would return error
2789
2922
 *    as a reply if the op handler do not return HGFS_ERROR_SUCCESS.
2790
2923
 *
2791
2924
 *    NOTE: If any op handler needs to keep packetIn around for sending replies
2793
2926
 *    make a copy of it. The validity of packetIn for the HGFS server is only
2794
2927
 *    within the scope of this function.
2795
2928
 *
2796
 
 *    Definitions of Meta Packet, Data packet can be looked up in hgfsChannelVmci.c
 
2929
 *    Definitions of Meta Packet, Data packet can be looked up in
 
2930
 *    hgfsChannelVmci.c
2797
2931
 *
2798
2932
 * Results:
2799
2933
 *    None
2829
2963
      return;
2830
2964
   }
2831
2965
 
 
2966
   packet->id = input->id;
2832
2967
   HGFS_ASSERT_MINIMUM_OP(input->op);
2833
2968
   if (HGFS_ERROR_SUCCESS == status) {
2834
2969
      HGFS_ASSERT_INPUT(input);
2835
 
      if (HgfsValidatePacket(input->metaPacket, input->metaPacketSize, input->v4header) &&
 
2970
      if (HgfsValidatePacket(input->metaPacket, input->metaPacketSize,
 
2971
                             input->v4header) &&
2836
2972
          (input->op < ARRAYSIZE(handlers)) &&
2837
2973
          (input->metaPacketSize >= handlers[input->op].minReqSize)) {
2838
2974
         /* Initial validation passed, process the client request now. */
2839
2975
         packet->processedAsync = packet->supportsAsync &&
2840
 
                                  (handlers[input->op].reqType == REQ_ASYNC);
 
2976
                                         (handlers[input->op].reqType == REQ_ASYNC);
2841
2977
         if (packet->processedAsync) {
2842
2978
            LOG(4, ("%s: %d: @@Async\n", __FUNCTION__, __LINE__));
2843
2979
#ifndef VMX86_TOOLS
2847
2983
             */
2848
2984
            HSPU_PutMetaPacket(packet, session);
2849
2985
            input->metaPacket = NULL;
 
2986
            Atomic_Inc(&gHgfsAsyncCounter);
2850
2987
 
2851
2988
            /* Remove pending requests during poweroff. */
2852
2989
            Poll_Callback(POLL_CS_MAIN,
2870
3007
          * operation.
2871
3008
          */
2872
3009
         status = HGFS_ERROR_PROTOCOL;
2873
 
         LOG(4, ("%s: %d: Possible BUG! Malformed packet.\n", __FUNCTION__, __LINE__));
 
3010
         LOG(4, ("%s: %d: Possible BUG! Malformed packet.\n", __FUNCTION__,
 
3011
                 __LINE__));
2874
3012
      }
2875
3013
   }
2876
3014
   HGFS_ASSERT_CLIENT(input->op);
2886
3024
/*
2887
3025
 *-----------------------------------------------------------------------------
2888
3026
 *
 
3027
 * HgfsServerCleanupDeletedFolders --
 
3028
 *
 
3029
 *    This function iterates through all shared folders and removes all
 
3030
 *    deleted shared folders, removes them from notification package and
 
3031
 *    from the folders list.
 
3032
 *
 
3033
 * Results:
 
3034
 *    None.
 
3035
 *
 
3036
 * Side effects:
 
3037
 *    None.
 
3038
 *
 
3039
 *-----------------------------------------------------------------------------
 
3040
 */
 
3041
 
 
3042
static void
 
3043
HgfsServerCleanupDeletedFolders(void)
 
3044
{
 
3045
   DblLnkLst_Links *link, *nextElem;
 
3046
 
 
3047
   MXUser_AcquireExclLock(gHgfsSharedFoldersLock);
 
3048
   DblLnkLst_ForEachSafe(link, nextElem, &gHgfsSharedFoldersList) {
 
3049
      HgfsSharedFolderProperties *folder =
 
3050
         DblLnkLst_Container(link, HgfsSharedFolderProperties, links);
 
3051
      if (folder->markedForDeletion) {
 
3052
         if (!HgfsNotify_RemoveSharedFolder(folder->notificationHandle)) {
 
3053
            LOG(4, ("Problem removing %d shared folder handle\n",
 
3054
                    folder->notificationHandle));
 
3055
         }
 
3056
         DblLnkLst_Unlink1(link);
 
3057
         free(folder);
 
3058
      }
 
3059
   }
 
3060
   MXUser_ReleaseExclLock(gHgfsSharedFoldersLock);
 
3061
}
 
3062
 
 
3063
 
 
3064
/*
 
3065
 *-----------------------------------------------------------------------------
 
3066
 *
 
3067
 * HgfsServer_RegisterSharedFolder --
 
3068
 *
 
3069
 *    This is a callback function which is invoked by hgfsServerManagement
 
3070
 *    for every shared folder when something changed in shared folders
 
3071
 *    configuration. The function iterates through the list of existing
 
3072
 *    shared folders trying to locate an entry with the shareName. If the
 
3073
 *    entry is found the function returns corresponding handle. Otherwise
 
3074
 *    it creates a new entry and assigns a new handle to it.
 
3075
 *
 
3076
 *    Currently there is no notification that a shared folder has been
 
3077
 *    deleted. The only way to find out that a shred folder is deleted
 
3078
 *    is to notice that it is not enumerated any more. Thus an explicit
 
3079
 *    "end of list" notification is needed. "sharedFolder == NULL" notifies
 
3080
 *    that enumeration is completed which allows to delete all shared
 
3081
 *    folders that were not mentioned during current enumeration.
 
3082
 *
 
3083
 * Results:
 
3084
 *    HgfsSharedFolderHandle for the entry.
 
3085
 *
 
3086
 * Side effects:
 
3087
 *    May add an entry to known shared folders list.
 
3088
 *
 
3089
 *-----------------------------------------------------------------------------
 
3090
 */
 
3091
 
 
3092
HgfsSharedFolderHandle
 
3093
HgfsServer_RegisterSharedFolder(const char *shareName,   // IN: shared folder name
 
3094
                                const char *sharePath,   // IN: shared folder path
 
3095
                                Bool addFolder)          // IN: add or remove folder
 
3096
{
 
3097
   DblLnkLst_Links *link, *nextElem;
 
3098
   HgfsSharedFolderHandle result = HGFS_INVALID_FOLDER_HANDLE;
 
3099
 
 
3100
   if (!gHgfsDirNotifyActive) {
 
3101
      return HGFS_INVALID_FOLDER_HANDLE;
 
3102
   }
 
3103
 
 
3104
   if (NULL == shareName) {
 
3105
      /*
 
3106
       * The function is invoked with shareName NULL when all shares has been
 
3107
       * enumerated.
 
3108
       * Need to delete all shared folders that were marked for deletion.
 
3109
       */
 
3110
      HgfsServerCleanupDeletedFolders();
 
3111
      return HGFS_INVALID_FOLDER_HANDLE;
 
3112
   }
 
3113
 
 
3114
   MXUser_AcquireExclLock(gHgfsSharedFoldersLock);
 
3115
 
 
3116
   DblLnkLst_ForEachSafe(link, nextElem, &gHgfsSharedFoldersList) {
 
3117
      HgfsSharedFolderProperties *folder =
 
3118
         DblLnkLst_Container(link, HgfsSharedFolderProperties, links);
 
3119
      if (strcmp(folder->name, shareName) == 0) {
 
3120
         result = folder->notificationHandle;
 
3121
         folder->markedForDeletion = !addFolder;
 
3122
         break;
 
3123
      }
 
3124
   }
 
3125
   if (addFolder && HGFS_INVALID_FOLDER_HANDLE == result) {
 
3126
      result = HgfsNotify_AddSharedFolder(sharePath, shareName);
 
3127
      if (HGFS_INVALID_FOLDER_HANDLE != result) {
 
3128
         HgfsSharedFolderProperties *folder =
 
3129
            (HgfsSharedFolderProperties *)Util_SafeMalloc(sizeof *folder);
 
3130
         folder->notificationHandle = result;
 
3131
         folder->name = Util_SafeStrdup(shareName);
 
3132
         folder->markedForDeletion = FALSE;
 
3133
         DblLnkLst_Init(&folder->links);
 
3134
         DblLnkLst_LinkLast(&gHgfsSharedFoldersList, &folder->links);
 
3135
      }
 
3136
   }
 
3137
   MXUser_ReleaseExclLock(gHgfsSharedFoldersLock);
 
3138
   return result;
 
3139
}
 
3140
 
 
3141
 
 
3142
/*
 
3143
 *-----------------------------------------------------------------------------
 
3144
 *
 
3145
 * HgfsServerGetShareHandle --
 
3146
 *
 
3147
 *    The function returns shared folder notification handle for the specified
 
3148
 *    shared folder.
 
3149
 *
 
3150
 * Results:
 
3151
 *    HgfsSharedFolderHandle that corresponds to the shared folder.
 
3152
 *
 
3153
 * Side effects:
 
3154
 *    None.
 
3155
 *
 
3156
 *-----------------------------------------------------------------------------
 
3157
 */
 
3158
 
 
3159
static HgfsSharedFolderHandle
 
3160
HgfsServerGetShareHandle(const char *shareName)  // IN: name of the shared folder
 
3161
{
 
3162
   DblLnkLst_Links *link;
 
3163
   HgfsSharedFolderHandle result = HGFS_INVALID_FOLDER_HANDLE;
 
3164
 
 
3165
   if (!gHgfsDirNotifyActive) {
 
3166
      return HGFS_INVALID_FOLDER_HANDLE;
 
3167
   }
 
3168
 
 
3169
   MXUser_AcquireExclLock(gHgfsSharedFoldersLock);
 
3170
 
 
3171
   DblLnkLst_ForEach(link, &gHgfsSharedFoldersList) {
 
3172
      HgfsSharedFolderProperties *folder =
 
3173
         DblLnkLst_Container(link, HgfsSharedFolderProperties, links);
 
3174
      if (strcmp(folder->name, shareName) == 0) {
 
3175
         result = folder->notificationHandle;
 
3176
         break;
 
3177
      }
 
3178
   }
 
3179
   MXUser_ReleaseExclLock(gHgfsSharedFoldersLock);
 
3180
   return result;
 
3181
}
 
3182
 
 
3183
 
 
3184
/*
 
3185
 *-----------------------------------------------------------------------------
 
3186
 *
 
3187
 * HgfsServerGetShareName --
 
3188
 *
 
3189
 *    Get the share name for a shared folder handle by looking at the
 
3190
 *    requested handle, finding the matching share (if any), and returning
 
3191
 *    the share's name.
 
3192
 *
 
3193
 * Results:
 
3194
 *    An Bool value indicating if the result is returned.
 
3195
 *
 
3196
 * Side effects:
 
3197
 *    None
 
3198
 *
 
3199
 *-----------------------------------------------------------------------------
 
3200
 */
 
3201
 
 
3202
static Bool
 
3203
HgfsServerGetShareName(HgfsSharedFolderHandle sharedFolder, // IN: Notify handle
 
3204
                       size_t *shareNameLen,                // OUT: Name length
 
3205
                       char **shareName)                    // OUT: Share name
 
3206
{
 
3207
   Bool result = FALSE;
 
3208
   DblLnkLst_Links *link;
 
3209
 
 
3210
   if (!gHgfsDirNotifyActive) {
 
3211
      return FALSE;
 
3212
   }
 
3213
 
 
3214
   MXUser_AcquireExclLock(gHgfsSharedFoldersLock);
 
3215
 
 
3216
   DblLnkLst_ForEach(link, &gHgfsSharedFoldersList) {
 
3217
      HgfsSharedFolderProperties *folder =
 
3218
         DblLnkLst_Container(link, HgfsSharedFolderProperties, links);
 
3219
      if (folder->notificationHandle == sharedFolder) {
 
3220
         *shareName = Util_SafeStrdup(folder->name);
 
3221
         result = TRUE;
 
3222
         *shareNameLen = strlen(*shareName);
 
3223
         break;
 
3224
      }
 
3225
   }
 
3226
   MXUser_ReleaseExclLock(gHgfsSharedFoldersLock);
 
3227
   return result;
 
3228
}
 
3229
 
 
3230
 
 
3231
/*
 
3232
 *-----------------------------------------------------------------------------
 
3233
 *
2889
3234
 * HgfsServer_InitState --
2890
3235
 *
2891
3236
 *    Initialize the global server state
2903
3248
HgfsServer_InitState(HgfsServerSessionCallbacks **callbackTable,  // IN/OUT: our callbacks
2904
3249
                     HgfsServerStateLogger *serverMgrData)        // IN: mgr callback
2905
3250
{
 
3251
   Bool result = TRUE;
 
3252
 
2906
3253
   ASSERT(callbackTable);
2907
3254
 
2908
3255
   /* Save any server manager data for logging state updates.*/
2911
3258
   maxCachedOpenNodes = Config_GetLong(MAX_CACHED_FILENODES,
2912
3259
                                       "hgfs.fdCache.maxNodes");
2913
3260
 
2914
 
#ifndef VMX86_TOOLS
2915
 
   if (Config_GetBool(FALSE, "hgfs.alwaysUseHostTime")) {
2916
 
      alwaysUseHostTime = TRUE;
2917
 
   }
2918
 
#endif
2919
 
 
2920
 
 
2921
 
#ifdef VMX86_TOOLS
2922
 
   hgfsStaticSession.session = NULL;
2923
 
   hgfsStaticSession.bufferOut = NULL;
2924
 
   hgfsStaticSession.bufferOutLen = 0;
2925
 
#endif
2926
 
 
2927
 
   if (HgfsNotify_Init() == 0) {
2928
 
      hgfsChangeNotificationSupported = TRUE;
2929
 
   }
2930
 
 
2931
 
   if (!HgfsServerPlatformInit()) {
2932
 
      LOG(4, ("Could not initialize server platform specific \n"));
2933
 
 
2934
 
      return FALSE;
2935
 
   }
2936
 
 
2937
 
   *callbackTable = &hgfsServerSessionCBTable;
2938
 
 
2939
 
   return TRUE;
 
3261
   alwaysUseHostTime = Config_GetBool(FALSE, "hgfs.alwaysUseHostTime");
 
3262
 
 
3263
   /*
 
3264
    * Initialize the globals for handling the active shared folders.
 
3265
    */
 
3266
 
 
3267
   gHgfsAsyncLock = NULL;
 
3268
   gHgfsAsyncVar = NULL;
 
3269
   Atomic_Write(&gHgfsAsyncCounter, 0);
 
3270
 
 
3271
   DblLnkLst_Init(&gHgfsSharedFoldersList);
 
3272
   gHgfsSharedFoldersLock = MXUser_CreateExclLock("sharedFoldersLock",
 
3273
                                                  RANK_hgfsSharedFolders);
 
3274
   if (NULL != gHgfsSharedFoldersLock) {
 
3275
      gHgfsAsyncLock = MXUser_CreateExclLock("asyncLock",
 
3276
                                             RANK_hgfsSharedFolders);
 
3277
      if (NULL != gHgfsAsyncLock) {
 
3278
         gHgfsAsyncVar = MXUser_CreateCondVarExclLock(gHgfsAsyncLock);
 
3279
         if (NULL != gHgfsAsyncVar) {
 
3280
            if (!HgfsServerPlatformInit()) {
 
3281
               LOG(4, ("Could not initialize server platform specific \n"));
 
3282
               result = FALSE;
 
3283
            }
 
3284
         } else {
 
3285
            LOG(4, ("%s: Could not create async counter cond var.\n",
 
3286
                    __FUNCTION__));
 
3287
            result = FALSE;
 
3288
         }
 
3289
      } else {
 
3290
         LOG(4, ("%s: Could not create async counter mutex.\n", __FUNCTION__));
 
3291
         result = FALSE;
 
3292
      }
 
3293
   } else {
 
3294
      LOG(4, ("%s: Could not create shared folders mutex.\n", __FUNCTION__));
 
3295
      result = FALSE;
 
3296
   }
 
3297
 
 
3298
   if (result) {
 
3299
      *callbackTable = &hgfsServerSessionCBTable;
 
3300
      if (Config_GetBool(TRUE, "isolation.tools.hgfs.notify.enable")) {
 
3301
         gHgfsDirNotifyActive = HgfsNotify_Init() == HGFS_STATUS_SUCCESS;
 
3302
      }
 
3303
      gHgfsInitialized = TRUE;
 
3304
   } else {
 
3305
      HgfsServer_ExitState(); // Cleanup partially initialized state
 
3306
   }
 
3307
 
 
3308
   return result;
2940
3309
}
2941
3310
 
2942
3311
 
2963
3332
void
2964
3333
HgfsServer_ExitState(void)
2965
3334
{
2966
 
 
2967
 
#ifdef VMX86_TOOLS
2968
 
   if (hgfsStaticSession.session != NULL) {
2969
 
      HgfsServerSessionPut(hgfsStaticSession.session);
2970
 
   }
2971
 
#endif
2972
 
 
2973
 
   if (hgfsChangeNotificationSupported) {
 
3335
   gHgfsInitialized = FALSE;
 
3336
 
 
3337
   if (gHgfsDirNotifyActive) {
2974
3338
      HgfsNotify_Shutdown();
 
3339
      gHgfsDirNotifyActive = FALSE;
 
3340
   }
 
3341
 
 
3342
   if (NULL != gHgfsSharedFoldersLock) {
 
3343
      MXUser_DestroyExclLock(gHgfsSharedFoldersLock);
 
3344
      gHgfsSharedFoldersLock = NULL;
 
3345
   }
 
3346
 
 
3347
   if (NULL != gHgfsAsyncLock) {
 
3348
      MXUser_DestroyExclLock(gHgfsAsyncLock);
 
3349
      gHgfsAsyncLock = NULL;
 
3350
   }
 
3351
 
 
3352
   if (NULL != gHgfsAsyncVar) {
 
3353
      MXUser_DestroyCondVar(gHgfsAsyncVar);
 
3354
      gHgfsAsyncVar = NULL;
2975
3355
   }
2976
3356
 
2977
3357
   HgfsServerPlatformDestroy();
3004
3384
/*
3005
3385
 *-----------------------------------------------------------------------------
3006
3386
 *
 
3387
 * HgfsServerSetSessionCapability --
 
3388
 *
 
3389
 *    Sets session capability for a specific operation code.
 
3390
 *
 
3391
 * Results:
 
3392
 *    TRUE is the capability for the operation has been changed.
 
3393
 *    FALSE if the operation is not represented in the capabilities array.
 
3394
 *
 
3395
 * Side effects:
 
3396
 *    None
 
3397
 *
 
3398
 *-----------------------------------------------------------------------------
 
3399
 */
 
3400
 
 
3401
Bool
 
3402
HgfsServerSetSessionCapability(HgfsOp op,                  // IN: operation code
 
3403
                               uint32 flags,               // IN: flags that describe level of support
 
3404
                               HgfsSessionInfo *session)   // INOUT: session to update
 
3405
{
 
3406
   int i;
 
3407
   Bool result = FALSE;
 
3408
 
 
3409
   for ( i = 0; i < ARRAYSIZE(session->hgfsSessionCapabilities); i++) {
 
3410
      if (session->hgfsSessionCapabilities[i].op == op) {
 
3411
         session->hgfsSessionCapabilities[i].flags = flags;
 
3412
         result = TRUE;
 
3413
      }
 
3414
   }
 
3415
   LOG(4, ("%s: Setting capabilitiy flags %x for op code %d %s\n",
 
3416
           __FUNCTION__, flags, op, result ? "succeeded" : "failed"));
 
3417
 
 
3418
   return result;
 
3419
}
 
3420
 
 
3421
 
 
3422
/*
 
3423
 *-----------------------------------------------------------------------------
 
3424
 *
 
3425
 * HgfsServerEnumerateSharedFolders --
 
3426
 *
 
3427
 *    Enumerates all exisitng shared folders and registers shared folders with
 
3428
 *    directory notification package.
 
3429
 *
 
3430
 * Results:
 
3431
 *    None.
 
3432
 *
 
3433
 * Side effects:
 
3434
 *    None.
 
3435
 *
 
3436
 *-----------------------------------------------------------------------------
 
3437
 */
 
3438
 
 
3439
static Bool
 
3440
HgfsServerEnumerateSharedFolders(void)
 
3441
{
 
3442
   void *state;
 
3443
   Bool success = FALSE;
 
3444
 
 
3445
   state = HgfsServerPolicy_GetSharesInit();
 
3446
   if (NULL != state) {
 
3447
      Bool done;
 
3448
 
 
3449
      do {
 
3450
         char const *shareName;
 
3451
         size_t len;
 
3452
 
 
3453
         success = HgfsServerPolicy_GetShares(state, &shareName, &len, &done);
 
3454
         if (success && !done) {
 
3455
            HgfsSharedFolderHandle handle;
 
3456
            char const *sharePath;
 
3457
            size_t sharePathLen;
 
3458
            HgfsNameStatus nameStatus;
 
3459
 
 
3460
            nameStatus = HgfsServerPolicy_GetSharePath(shareName, len,
 
3461
                                                       HGFS_OPEN_MODE_READ_ONLY,
 
3462
                                                       &sharePathLen, &sharePath);
 
3463
            if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
 
3464
               handle = HgfsServer_RegisterSharedFolder(shareName, sharePath,
 
3465
                                                        TRUE);
 
3466
               success = handle != HGFS_INVALID_FOLDER_HANDLE;
 
3467
            }
 
3468
         }
 
3469
      } while (!done && success);
 
3470
 
 
3471
      HgfsServerPolicy_GetSharesCleanup(state);
 
3472
   }
 
3473
   return success;
 
3474
}
 
3475
 
 
3476
 
 
3477
/*
 
3478
 *-----------------------------------------------------------------------------
 
3479
 *
3007
3480
 * HgfsServerSessionConnect --
3008
3481
 *
3009
3482
 *    Initialize a new client session.
3023
3496
static Bool
3024
3497
HgfsServerSessionConnect(void *transportData,                         // IN: transport session context
3025
3498
                         HgfsServerChannelCallbacks *channelCbTable,  // IN: Channel callbacks
 
3499
                         uint32 channelCapabililies,                  // IN: channel capabilities
3026
3500
                         void **sessionData)                          // OUT: server session context
3027
3501
{
3028
3502
   int i;
3061
3535
      MXUser_DestroyExclLock(session->fileIOLock);
3062
3536
      MXUser_DestroyExclLock(session->nodeArrayLock);
3063
3537
      free(session);
3064
 
      LOG(4, ("%s: Could not create search array sync mutex.\n", __FUNCTION__));
 
3538
      LOG(4, ("%s: Could not create search array sync mutex.\n",
 
3539
              __FUNCTION__));
3065
3540
 
3066
3541
      return FALSE;
3067
3542
   }
3068
3543
 
3069
3544
   session->sessionId = HgfsGenerateSessionId();
3070
3545
   session->maxPacketSize = MAX_SERVER_PACKET_SIZE_V4;
 
3546
   session->activeNotification = FALSE;
3071
3547
   /*
3072
3548
    * Initialize the node handling components.
3073
3549
    */
3077
3553
 
3078
3554
   /* Allocate array of FileNodes and add them to free list. */
3079
3555
   session->numNodes = NUM_FILE_NODES;
3080
 
   session->nodeArray = Util_SafeCalloc(session->numNodes, sizeof (HgfsFileNode));
 
3556
   session->nodeArray = Util_SafeCalloc(session->numNodes,
 
3557
                                        sizeof (HgfsFileNode));
3081
3558
   session->numCachedOpenNodes = 0;
3082
3559
   session->numCachedLockedNodes = 0;
3083
3560
 
3096
3573
 
3097
3574
   /* Allocate array of searches and add them to free list. */
3098
3575
   session->numSearches = NUM_SEARCHES;
3099
 
   session->searchArray = Util_SafeCalloc(session->numSearches, sizeof (HgfsSearch));
 
3576
   session->searchArray = Util_SafeCalloc(session->numSearches,
 
3577
                                          sizeof (HgfsSearch));
3100
3578
 
3101
3579
   for (i = 0; i < session->numSearches; i++) {
3102
3580
      DblLnkLst_Init(&session->searchArray[i].links);
3115
3593
   session->channelCbTable = channelCbTable;
3116
3594
   Atomic_Write(&session->refCount, 0);
3117
3595
 
 
3596
   /* Get common to all sessions capabiities. */
 
3597
   HgfsServerGetDefaultCapabilities(session->hgfsSessionCapabilities,
 
3598
                                    &session->numberOfCapabilities);
 
3599
 
3118
3600
   /* Give our session a reference to hold while we are open. */
3119
3601
   HgfsServerSessionGet(session);
3120
3602
   *sessionData = session;
3121
3603
 
 
3604
   if (channelCapabililies & HGFS_CHANNEL_SHARED_MEM) {
 
3605
      HgfsServerSetSessionCapability(HGFS_OP_READ_FAST_V4,
 
3606
                                     HGFS_REQUEST_SUPPORTED, session);
 
3607
      HgfsServerSetSessionCapability(HGFS_OP_WRITE_FAST_V4,
 
3608
                                     HGFS_REQUEST_SUPPORTED, session);
 
3609
      if (gHgfsDirNotifyActive) {
 
3610
         if (HgfsServerEnumerateSharedFolders()) {
 
3611
            HgfsServerSetSessionCapability(HGFS_OP_SET_WATCH_V4,
 
3612
                                           HGFS_REQUEST_SUPPORTED, session);
 
3613
            HgfsServerSetSessionCapability(HGFS_OP_REMOVE_WATCH_V4,
 
3614
                                           HGFS_REQUEST_SUPPORTED, session);
 
3615
            session->activeNotification = TRUE;
 
3616
         } else {
 
3617
            HgfsServerSetSessionCapability(HGFS_OP_SET_WATCH_V4,
 
3618
                                           HGFS_REQUEST_NOT_SUPPORTED, session);
 
3619
            HgfsServerSetSessionCapability(HGFS_OP_REMOVE_WATCH_V4,
 
3620
                                           HGFS_REQUEST_NOT_SUPPORTED, session);
 
3621
         }
 
3622
      }
 
3623
   }
 
3624
 
3122
3625
   return TRUE;
3123
3626
}
3124
3627
 
3153
3656
   ASSERT(session->searchArray);
3154
3657
 
3155
3658
   session->state = HGFS_SESSION_STATE_CLOSED;
 
3659
 
 
3660
   if (session->activeNotification) {
 
3661
      HgfsNotify_CleanupSession(session);
 
3662
   }
3156
3663
}
3157
3664
 
3158
3665
 
3314
3821
}
3315
3822
 
3316
3823
 
3317
 
#ifdef VMX86_TOOLS
3318
 
/*
3319
 
 *----------------------------------------------------------------------------
3320
 
 *
3321
 
 * HgfsServer_ProcessPacket --
3322
 
 *
3323
 
 *    Process packet not associated with any session.
3324
 
 *
3325
 
 *    This function is used in the HGFS server inside Tools.
3326
 
 *
3327
 
 *    Create an internal session if not already created, and process the packet.
3328
 
 *
3329
 
 * Results:
3330
 
 *    None
3331
 
 *
3332
 
 * Side effects:
3333
 
 *    None
3334
 
 *
3335
 
 *----------------------------------------------------------------------------
3336
 
 */
3337
 
 
3338
 
void
3339
 
HgfsServer_ProcessPacket(char const *packetIn,   // IN: incoming packet
3340
 
                         char *packetOut,        // OUT: outgoing packet
3341
 
                         size_t *packetLen)     // IN/OUT: packet length
3342
 
{
3343
 
   HgfsPacket packet;
3344
 
   ASSERT(packetIn);
3345
 
   ASSERT(packetOut);
3346
 
   ASSERT(packetLen);
3347
 
 
3348
 
   if (*packetLen == 0) {
3349
 
      return;
3350
 
   }
3351
 
 
3352
 
   /*
3353
 
    * Create the session if not already created.
3354
 
    * This session is destroyed in HgfsServer_ExitState.
3355
 
    */
3356
 
 
3357
 
   if (hgfsStaticSession.session == NULL) {
3358
 
      if (!HgfsServerSessionConnect(NULL, NULL,
3359
 
                                    (void **)&hgfsStaticSession.session)) {
3360
 
         *packetLen = 0;
3361
 
 
3362
 
         return;
3363
 
      }
3364
 
 
3365
 
      /* Mark the session as internal. */
3366
 
      hgfsStaticSession.session->type = HGFS_SESSION_TYPE_INTERNAL;
3367
 
   }
3368
 
 
3369
 
   memset(&packet, 0, sizeof packet);
3370
 
   packet.iov[0].va = (void *)packetIn;
3371
 
   packet.iov[0].len = *packetLen;
3372
 
   packet.iovCount = 1;
3373
 
   packet.metaPacket = (void *)packetIn;
3374
 
   packet.metaPacketSize = *packetLen;
3375
 
   packet.replyPacket = packetOut;
3376
 
   packet.replyPacketSize = HGFS_LARGE_PACKET_MAX;
3377
 
   packet.supportsAsync = FALSE;
3378
 
 
3379
 
   HgfsServerSessionReceive(&packet,
3380
 
                            hgfsStaticSession.session);
3381
 
 
3382
 
   /*
3383
 
    * At this point, all the HGFS ops send reply synchronously. So
3384
 
    * we should have the reply by now.
3385
 
    * XXX This should change if any async replies are expected.
3386
 
    */
3387
 
 
3388
 
   ASSERT(hgfsStaticSession.bufferOut);
3389
 
 
3390
 
   *packetLen = hgfsStaticSession.bufferOutLen;
3391
 
 
3392
 
   HgfsServerSessionSendComplete(&packet,
3393
 
                                 hgfsStaticSession.session);
3394
 
   hgfsStaticSession.bufferOut = NULL;
3395
 
}
3396
 
#endif
3397
 
 
3398
 
 
3399
3824
/*
3400
3825
 *----------------------------------------------------------------------------
3401
3826
 *
3428
3853
/*
3429
3854
 *----------------------------------------------------------------------------
3430
3855
 *
 
3856
 * HgfsServer_Quiesce --
 
3857
 *
 
3858
 *    The function is called when VM is about to take a snapshot and
 
3859
 *    when creation of the snapshot completed. When the freeze is TRUE the
 
3860
 *    function quiesces all asynchronous and background activity to prevent
 
3861
 *    interactions with snapshots and waits until there is no such activity.
 
3862
 *    When freeze is FALSE the function restarts background activity that
 
3863
 *    has been suspended previously.
 
3864
 *
 
3865
 * Results:
 
3866
 *    None.
 
3867
 *
 
3868
 * Side effects:
 
3869
 *    None.
 
3870
 *
 
3871
 *----------------------------------------------------------------------------
 
3872
 */
 
3873
 
 
3874
void
 
3875
HgfsServer_Quiesce(Bool freeze)  // IN:
 
3876
{
 
3877
   if (!gHgfsInitialized) {
 
3878
      return;
 
3879
   }
 
3880
 
 
3881
   if (freeze) {
 
3882
      /* Suspend background activity. */
 
3883
      if (gHgfsDirNotifyActive) {
 
3884
         HgfsNotify_Suspend();
 
3885
      }
 
3886
      /* Wait for outstanding asynchronous requests to complete. */
 
3887
      MXUser_AcquireExclLock(gHgfsAsyncLock);
 
3888
      while (Atomic_Read(&gHgfsAsyncCounter)) {
 
3889
         MXUser_WaitCondVarExclLock(gHgfsAsyncLock, gHgfsAsyncVar);
 
3890
      }
 
3891
      MXUser_ReleaseExclLock(gHgfsAsyncLock);
 
3892
   } else {
 
3893
      /* Resume background activity. */
 
3894
      if (gHgfsDirNotifyActive) {
 
3895
         HgfsNotify_Resume();
 
3896
      }
 
3897
   }
 
3898
}
 
3899
 
 
3900
 
 
3901
/*
 
3902
 *----------------------------------------------------------------------------
 
3903
 *
 
3904
 * HgfsNotifyPacketSent --
 
3905
 *
 
3906
 *    Decrements counter of outstanding asynchronous packets
 
3907
 *    and signal conditional variable when the counter
 
3908
 *    becomes 0.
 
3909
 *
 
3910
 * Results:
 
3911
 *    TRUE on success, FALSE on error.
 
3912
 *
 
3913
 * Side effects:
 
3914
 *    None.
 
3915
 *
 
3916
 *----------------------------------------------------------------------------
 
3917
 */
 
3918
 
 
3919
static void
 
3920
HgfsNotifyPacketSent(void)
 
3921
{
 
3922
   if (Atomic_FetchAndDec(&gHgfsAsyncCounter) == 1) {
 
3923
      MXUser_AcquireExclLock(gHgfsAsyncLock);
 
3924
      MXUser_BroadcastCondVar(gHgfsAsyncVar);
 
3925
      MXUser_ReleaseExclLock(gHgfsAsyncLock);
 
3926
   }
 
3927
}
 
3928
 
 
3929
 
 
3930
/*
 
3931
 *----------------------------------------------------------------------------
 
3932
 *
3431
3933
 * HgfsPacketSend --
3432
3934
 *
3433
3935
 *    Send the packet.
3449
3951
               HgfsSendFlags flags)           // IN: flags for how to process
3450
3952
{
3451
3953
   Bool result = FALSE;
 
3954
   Bool notificationNeeded = packet->guestInitiated && packet->processedAsync;
3452
3955
 
3453
3956
   ASSERT(packet);
3454
3957
   ASSERT(session);
3455
3958
 
3456
3959
   if (session->state == HGFS_SESSION_STATE_OPEN) {
3457
 
#ifndef VMX86_TOOLS
 
3960
      packet->replyPacketSize = packetOutLen;
3458
3961
      ASSERT(session->type == HGFS_SESSION_TYPE_REGULAR);
3459
3962
      result = session->channelCbTable->send(session->transportData,
3460
3963
                                             packet, packetOut,
3461
3964
                                             packetOutLen, flags);
3462
 
#else
3463
 
      /* This is internal session. */
3464
 
      ASSERT(session->type == HGFS_SESSION_TYPE_INTERNAL);
3465
 
      hgfsStaticSession.bufferOut = packetOut;
3466
 
      hgfsStaticSession.bufferOutLen = packetOutLen;
3467
 
      result = TRUE;
3468
 
#endif
3469
3965
   }
3470
3966
 
 
3967
   if (notificationNeeded) {
 
3968
      HgfsNotifyPacketSent();
 
3969
   }
3471
3970
   return result;
3472
3971
}
3473
3972
 
3560
4059
         continue;
3561
4060
      }
3562
4061
 
 
4062
      if (HgfsSearchIsBaseNameSpace(&session->searchArray[i])) {
 
4063
         /* Skip search of the base name space. Maybe stale but it is okay. */
 
4064
         continue;
 
4065
      }
 
4066
 
3563
4067
      handle = HgfsSearch2SearchHandle(&session->searchArray[i]);
3564
4068
      LOG(4, ("%s: Examining search (%s)\n", __FUNCTION__,
3565
4069
              session->searchArray[i].utf8Dir));
3616
4120
   HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
3617
4121
 
3618
4122
   HgfsInvalidateSessionObjects(shares, session);
3619
 
 
3620
 
#ifdef VMX86_TOOLS
3621
 
   if (hgfsStaticSession.session != NULL) {
3622
 
      HgfsInvalidateSessionObjects(shares, hgfsStaticSession.session);
3623
 
   }
3624
 
#endif
3625
4123
}
3626
4124
 
3627
4125
 
3734
4232
 
3735
4233
   inEnd = cpName + cpNameSize;
3736
4234
 
 
4235
   if (!Unicode_IsBufferValid(cpName, cpNameSize, STRING_ENCODING_UTF8)) {
 
4236
      LOG(4, ("%s: invalid UTF8 string @ %p\n", __FUNCTION__, cpName));
 
4237
      return HGFS_NAME_STATUS_FAILURE;
 
4238
   }
 
4239
 
3737
4240
   /*
3738
4241
    * Get first component.
3739
4242
    */
3754
4257
                                               len,
3755
4258
                                               &shareInfo->readPermissions,
3756
4259
                                               &shareInfo->writePermissions,
 
4260
                                               &shareInfo->handle,
3757
4261
                                               &shareInfo->rootDir);
3758
4262
   if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
3759
4263
      LOG(4, ("%s: No such share (%s)\n", __FUNCTION__, cpName));
3765
4269
   nameStatus = HgfsServerPolicy_GetShareOptions(cpName, len, &shareOptions);
3766
4270
   if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
3767
4271
      LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, cpName));
3768
 
 
3769
4272
      return nameStatus;
3770
4273
   }
3771
4274
 
3889
4392
      }
3890
4393
 
3891
4394
      free(myBufOut);
3892
 
      LOG(4, ("%s: name is \"%s\"\n", __FUNCTION__, myBufOut));
 
4395
      LOG(4, ("%s: name is \"%s\"\n", __FUNCTION__, tempPtr));
3893
4396
 
3894
4397
      /* Save returned pointers, update buffer length. */
3895
4398
      myBufOut = tempPtr;
4674
5177
   reply = HSPU_GetReplyPacket(packet, &replyPacketSize, session);
4675
5178
 
4676
5179
   if (reply && (replyPacketSize >= headerSize + payloadSize)) {
 
5180
      memset(reply, 0, headerSize + payloadSize);
4677
5181
      result = TRUE;
4678
5182
      if (payloadSize > 0) {
4679
5183
         *payload = reply + headerSize;
4742
5246
                                                requiredSize, payload,
4743
5247
                                                &reply->actualSize);
4744
5248
                  if (HGFS_ERROR_SUCCESS == status) {
 
5249
                     reply->reserved = 0;
4745
5250
                     replyPayloadSize = sizeof *reply +
4746
5251
                                         ((inlineDataSize > 0) ? reply->actualSize : 0);
4747
5252
                  }
5920
6425
/*
5921
6426
 *-----------------------------------------------------------------------------
5922
6427
 *
 
6428
 * HgfsServerSetDirWatchByHandle --
 
6429
 *
 
6430
 *    Sets directory notification watch request using directory handle.
 
6431
 *
 
6432
 * Results:
 
6433
 *    None.
 
6434
 *
 
6435
 * Side effects:
 
6436
 *    None
 
6437
 *
 
6438
 *-----------------------------------------------------------------------------
 
6439
 */
 
6440
 
 
6441
static HgfsInternalStatus
 
6442
HgfsServerSetDirWatchByHandle(HgfsInputParam *input,         // IN: Input params
 
6443
                              HgfsHandle dir,                // IN: directory handle
 
6444
                              uint32 events,                 // IN: event types to report
 
6445
                              Bool watchTree,                // IN: recursive watch
 
6446
                              HgfsSubscriberHandle *watchId) // OUT: watch id
 
6447
{
 
6448
   HgfsInternalStatus status;
 
6449
   char *fileName = NULL;
 
6450
   size_t fileNameSize;
 
6451
   HgfsSharedFolderHandle sharedFolder = HGFS_INVALID_FOLDER_HANDLE;
 
6452
 
 
6453
   ASSERT(watchId != NULL);
 
6454
 
 
6455
   if (HgfsHandle2NotifyInfo(dir, input->session, &fileName, &fileNameSize,
 
6456
                             &sharedFolder)) {
 
6457
      *watchId = HgfsNotify_AddSubscriber(sharedFolder, fileName, events, watchTree,
 
6458
                                          Hgfs_NotificationCallback, input->session);
 
6459
      status = (HGFS_INVALID_SUBSCRIBER_HANDLE == *watchId) ? HGFS_ERROR_INTERNAL :
 
6460
                                                              HGFS_ERROR_SUCCESS;
 
6461
   } else {
 
6462
      status = HGFS_ERROR_INTERNAL;
 
6463
   }
 
6464
   free(fileName);
 
6465
   return status;
 
6466
}
 
6467
 
 
6468
 
 
6469
/*
 
6470
 *-----------------------------------------------------------------------------
 
6471
 *
 
6472
 * HgfsServerSetDirWatchByName --
 
6473
 *
 
6474
 *    Sets directory notification watch request using directory name.
 
6475
 *
 
6476
 * Results:
 
6477
 *    None.
 
6478
 *
 
6479
 * Side effects:
 
6480
 *    None
 
6481
 *
 
6482
 *-----------------------------------------------------------------------------
 
6483
 */
 
6484
 
 
6485
static HgfsInternalStatus
 
6486
HgfsServerSetDirWatchByName(HgfsInputParam *input,         // IN: Input params
 
6487
                            char *cpName,                  // IN: directory name
 
6488
                            uint32 cpNameSize,             // IN: directory name length
 
6489
                            uint32 caseFlags,              // IN: case flags
 
6490
                            uint32 events,                 // IN: event types to report
 
6491
                            Bool watchTree,                // IN: recursive watch
 
6492
                            HgfsSubscriberHandle *watchId) // OUT: watch id
 
6493
{
 
6494
   HgfsInternalStatus status;
 
6495
   HgfsNameStatus nameStatus;
 
6496
   char *utf8Name = NULL;
 
6497
   size_t utf8NameLen;
 
6498
   HgfsShareInfo shareInfo;
 
6499
   HgfsSharedFolderHandle sharedFolder = HGFS_INVALID_FOLDER_HANDLE;
 
6500
 
 
6501
   ASSERT(cpName != NULL);
 
6502
   ASSERT(watchId != NULL);
 
6503
 
 
6504
   nameStatus = HgfsServerGetShareInfo(cpName, cpNameSize, caseFlags, &shareInfo,
 
6505
                                       &utf8Name, &utf8NameLen);
 
6506
   if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
 
6507
      char const *inEnd = cpName + cpNameSize;
 
6508
      char const *next;
 
6509
      int len;
 
6510
 
 
6511
      ASSERT(utf8Name);
 
6512
      /*
 
6513
       * Get first component.
 
6514
       */
 
6515
      len = CPName_GetComponent(cpName, inEnd, (char const **) &next);
 
6516
      if (len < 0) {
 
6517
         LOG(4, ("%s: get first component failed\n", __FUNCTION__));
 
6518
         nameStatus = HGFS_NAME_STATUS_FAILURE;
 
6519
      } else if (0 == len) {
 
6520
         /* See if we are dealing with the base of the namespace */
 
6521
         nameStatus = HGFS_NAME_STATUS_INCOMPLETE_BASE;
 
6522
      } else {
 
6523
         sharedFolder = HgfsServerGetShareHandle(cpName);
 
6524
      }
 
6525
 
 
6526
      if (HGFS_NAME_STATUS_COMPLETE == nameStatus &&
 
6527
          HGFS_INVALID_FOLDER_HANDLE != sharedFolder) {
 
6528
         if (cpNameSize > len + 1) {
 
6529
            size_t nameSize = cpNameSize - len - 1;
 
6530
            char tempBuf[HGFS_PATH_MAX];
 
6531
            char *tempPtr = tempBuf;
 
6532
            size_t tempSize = sizeof tempBuf;
 
6533
 
 
6534
            nameStatus = CPName_ConvertFrom((char const **) &next, &nameSize,
 
6535
                                            &tempSize, &tempPtr);
 
6536
            if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
 
6537
               *watchId = HgfsNotify_AddSubscriber(sharedFolder, tempBuf, events,
 
6538
                                                   watchTree, Hgfs_NotificationCallback,
 
6539
                                                   input->session);
 
6540
                status = (HGFS_INVALID_SUBSCRIBER_HANDLE == *watchId) ?
 
6541
                                              HGFS_ERROR_INTERNAL : HGFS_ERROR_SUCCESS;
 
6542
            } else {
 
6543
               LOG(4, ("%s: Conversion to platform specific name failed\n",
 
6544
                       __FUNCTION__));
 
6545
               status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
6546
            }
 
6547
         } else {
 
6548
            *watchId = HgfsNotify_AddSubscriber(sharedFolder, "", events, watchTree,
 
6549
                                                Hgfs_NotificationCallback,
 
6550
                                                input->session);
 
6551
            status = (HGFS_INVALID_SUBSCRIBER_HANDLE == *watchId) ? HGFS_ERROR_INTERNAL :
 
6552
                                                                    HGFS_ERROR_SUCCESS;
 
6553
         }
 
6554
      } else if (HGFS_NAME_STATUS_INCOMPLETE_BASE == nameStatus) {
 
6555
         LOG(4, ("%s: Notification for root share is not supported yet\n",
 
6556
                 __FUNCTION__));
 
6557
         status = HGFS_ERROR_INVALID_PARAMETER;
 
6558
      } else {
 
6559
         LOG(4, ("%s: file not found.\n", __FUNCTION__));
 
6560
         status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
6561
      }
 
6562
   } else {
 
6563
      LOG(4, ("%s: file not found.\n", __FUNCTION__));
 
6564
      status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
6565
   }
 
6566
   free(utf8Name);
 
6567
   return status;
 
6568
}
 
6569
 
 
6570
 
 
6571
/*
 
6572
 *-----------------------------------------------------------------------------
 
6573
 *
 
6574
 * HgfsServerSetDirNotifyWatch --
 
6575
 *
 
6576
 *    Handle a set directory notification watch request.
 
6577
 *
 
6578
 * Results:
 
6579
 *    None.
 
6580
 *
 
6581
 * Side effects:
 
6582
 *    None
 
6583
 *
 
6584
 *-----------------------------------------------------------------------------
 
6585
 */
 
6586
 
 
6587
static void
 
6588
HgfsServerSetDirNotifyWatch(HgfsInputParam *input)  // IN: Input params
 
6589
{
 
6590
   char *cpName;
 
6591
   size_t cpNameSize;
 
6592
   HgfsInternalStatus status;
 
6593
   HgfsHandle dir;
 
6594
   uint32 caseFlags;
 
6595
   size_t replyPayloadSize = 0;
 
6596
   uint32 flags;
 
6597
   uint32 events;
 
6598
   HgfsSubscriberHandle watchId = HGFS_INVALID_SUBSCRIBER_HANDLE;
 
6599
   Bool useHandle;
 
6600
 
 
6601
   HGFS_ASSERT_INPUT(input);
 
6602
 
 
6603
   /*
 
6604
    * If the active session does not support directory change notification - bail out
 
6605
    * with an error immediately. Otherwise setting watch may succeed but no notification
 
6606
    * will be delivered when a change occurs.
 
6607
    */
 
6608
   if (!input->session->activeNotification) {
 
6609
      HgfsServerCompleteRequest(HGFS_ERROR_PROTOCOL, 0, input);
 
6610
      return;
 
6611
   }
 
6612
 
 
6613
   if (HgfsUnpackSetWatchRequest(input->payload, input->payloadSize, input->op,
 
6614
                                 &useHandle, &cpName, &cpNameSize, &flags, &events,
 
6615
                                 &dir, &caseFlags)) {
 
6616
      Bool watchTree = 0 != (flags & HGFS_NOTIFY_FLAG_WATCH_TREE);
 
6617
      if (useHandle) {
 
6618
         status = HgfsServerSetDirWatchByHandle(input, dir, events, watchTree, &watchId);
 
6619
      } else {
 
6620
         status = HgfsServerSetDirWatchByName(input, cpName, cpNameSize, caseFlags,
 
6621
                                              events, watchTree, &watchId);
 
6622
      }
 
6623
      if (HGFS_ERROR_SUCCESS == status) {
 
6624
         if (!HgfsPackSetWatchReply(input->packet, input->metaPacket, input->op,
 
6625
                                    watchId, &replyPayloadSize, input->session)) {
 
6626
            status = HGFS_ERROR_INTERNAL;
 
6627
         }
 
6628
      }
 
6629
   } else {
 
6630
      status = HGFS_ERROR_PROTOCOL;
 
6631
   }
 
6632
 
 
6633
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
6634
}
 
6635
 
 
6636
 
 
6637
/*
 
6638
 *-----------------------------------------------------------------------------
 
6639
 *
 
6640
 * HgfsServerRemoveDirNotifyWatch --
 
6641
 *
 
6642
 *    Handle a remove directory notification watch request.
 
6643
 *
 
6644
 * Results:
 
6645
 *    None.
 
6646
 *
 
6647
 * Side effects:
 
6648
 *    None
 
6649
 *
 
6650
 *-----------------------------------------------------------------------------
 
6651
 */
 
6652
 
 
6653
static void
 
6654
HgfsServerRemoveDirNotifyWatch(HgfsInputParam *input)  // IN: Input params
 
6655
{
 
6656
   HgfsSubscriberHandle watchId;
 
6657
   HgfsInternalStatus status;
 
6658
   size_t replyPayloadSize = 0;
 
6659
 
 
6660
   HGFS_ASSERT_INPUT(input);
 
6661
 
 
6662
   if (HgfsUnpackRemoveWatchRequest(input->payload, input->payloadSize, input->op,
 
6663
                                    &watchId)) {
 
6664
      if (HgfsNotify_RemoveSubscriber(watchId)) {
 
6665
         status = HGFS_ERROR_SUCCESS;
 
6666
      } else {
 
6667
         status = HGFS_ERROR_INTERNAL;
 
6668
      }
 
6669
   } else {
 
6670
      status = HGFS_ERROR_PROTOCOL;
 
6671
   }
 
6672
   if (HGFS_ERROR_SUCCESS == status) {
 
6673
      if (!HgfsPackRemoveWatchReply(input->packet, input->metaPacket, input->op,
 
6674
         &replyPayloadSize, input->session)) {
 
6675
            status = HGFS_ERROR_INTERNAL;
 
6676
      }
 
6677
   }
 
6678
 
 
6679
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
6680
}
 
6681
 
 
6682
 
 
6683
/*
 
6684
 *-----------------------------------------------------------------------------
 
6685
 *
5923
6686
 * HgfsServerGetattr --
5924
6687
 *
5925
6688
 *    Handle a Getattr request.
6353
7116
 *    Gets a directory entry at specified offset.
6354
7117
 *
6355
7118
 * Results:
6356
 
 *    None.
 
7119
 *    A platform specific error or success.
6357
7120
 *
6358
7121
 * Side effects:
6359
7122
 *    None
6373
7136
{
6374
7137
   HgfsInternalStatus status;
6375
7138
   DirectoryEntry *dent;
 
7139
   Bool unescapeName = TRUE;
6376
7140
 
6377
7141
   dent = HgfsGetSearchResult(hgfsSearchHandle, session, requestedOffset, FALSE);
6378
7142
   if (dent) {
6433
7197
               memset(attr, 0, sizeof *attr);
6434
7198
               attr->requestType = savedOp;
6435
7199
               attr->type = HGFS_FILE_TYPE_REGULAR;
6436
 
               attr->mask = 0;
 
7200
               attr->mask = HGFS_ATTR_VALID_TYPE;
6437
7201
            }
6438
7202
 
6439
7203
            free(fullName);
6448
7212
      case DIRECTORY_SEARCH_TYPE_BASE:
6449
7213
 
6450
7214
         /*
 
7215
          * We only want to unescape names that we could have escaped.
 
7216
          * This cannot apply to our shares since they are created by the user.
 
7217
          * The client will take care of escaping anything it requires.
 
7218
          */
 
7219
         unescapeName = FALSE;
 
7220
         /*
6451
7221
          * For a search enumerating all shares, give the default attributes
6452
7222
          * for '.' and ".." (which aren't really shares anyway). Each real
6453
7223
          * share gets resolved into its full path, and gets its attributes
6527
7297
         NOT_IMPLEMENTED();
6528
7298
#endif
6529
7299
         /*
 
7300
          * We only want to unescape names that we could have escaped.
 
7301
          * This cannot apply to these entries.
 
7302
          */
 
7303
         unescapeName = FALSE;
 
7304
         /*
6530
7305
          * All "other" searches get the default attributes. This includes
6531
7306
          * an enumeration of drive, and the root enumeration (which contains
6532
7307
          * a "drive" dent and a "unc" dent).
6542
7317
       * We need to unescape the name before sending it back to the client
6543
7318
       */
6544
7319
      if (HGFS_ERROR_SUCCESS == status) {
6545
 
         *entryName = strdup(dent->d_name);
6546
 
         *nameLength = HgfsEscape_Undo(dent->d_name, length + 1);
 
7320
         *entryName = Util_SafeStrdup(dent->d_name);
 
7321
         if (unescapeName) {
 
7322
            *nameLength = HgfsEscape_Undo(*entryName, length + 1);
 
7323
         } else {
 
7324
            *nameLength = length;
 
7325
         }
6547
7326
         LOG(4, ("%s: dent name is \"%s\" len = %"FMTSZ"u\n", __FUNCTION__,
6548
7327
                 *entryName, *nameLength));
6549
7328
      } else {
6674
7453
      }
6675
7454
      if (HgfsPackCreateSessionReply(input->packet, input->metaPacket,
6676
7455
                                     &replyPayloadSize, input->session)) {
 
7456
 
 
7457
         /*
 
7458
          * XXX - TO BE RESTORED on session support implementation
 
7459
          * completion.
 
7460
          */
 
7461
#if defined HGFS_SESSION_SUPPORT
6677
7462
         HgfsServerSessionGet(input->session);
 
7463
#endif
6678
7464
         status = HGFS_ERROR_SUCCESS;
6679
7465
      } else {
6680
7466
         status = HGFS_ERROR_INTERNAL;
6709
7495
   HGFS_ASSERT_INPUT(input);
6710
7496
 
6711
7497
   HgfsServerCompleteRequest(HGFS_ERROR_SUCCESS, 0, input);
 
7498
   /*
 
7499
    * XXX - TO BE RESTORED on session support implementation
 
7500
    * completion.
 
7501
      */
 
7502
#if defined HGFS_SESSION_SUPPORT
6712
7503
   HgfsServerSessionPut(input->session);
 
7504
#endif
6713
7505
}
6714
7506
 
6715
7507
 
6818
7610
 *    Callback which is called by directory notification package when in response
6819
7611
 *    to a event.
6820
7612
 *
6821
 
 *    XXX:
6822
 
 *    The function must build directory notification packet and send it to the
6823
 
 *    client. At the moment it just logs a message, actual logic will be
6824
 
 *    implemented later when required infrastructure is ready.
 
7613
 *    The function builds directory notification packet and queues it to be sent
 
7614
 *    to the client. It processes one notification at a time. It relies on transport
 
7615
 *    to perform coalescing.
6825
7616
 *
6826
7617
 * Results:
6827
7618
 *    None.
6833
7624
 */
6834
7625
 
6835
7626
void
6836
 
Hgfs_NotificationCallback(HgfsSharedFolderHandle sharedFolder,
6837
 
                          HgfsSubscriberHandle subscriber,
6838
 
                          char* name,
6839
 
                          char* newName,
6840
 
                          uint32 mask)
 
7627
Hgfs_NotificationCallback(HgfsSharedFolderHandle sharedFolder, // IN: shared folder
 
7628
                          HgfsSubscriberHandle subscriber,     // IN: subsciber
 
7629
                          char* fileName,                      // IN: name of the file
 
7630
                          uint32 mask,                         // IN: event type
 
7631
                          struct HgfsSessionInfo *session)     // IN: session info
6841
7632
{
6842
 
    LOG(4, ("%s: notification for folder: %d index: %d file name %s "
6843
 
            "(new name %s) mask %x\n", __FUNCTION__, sharedFolder,
6844
 
            (int)subscriber, name, (newName == NULL) ? "" : newName,
6845
 
            mask));
 
7633
   HgfsPacket *packet;
 
7634
   size_t sizeNeeded;
 
7635
   char *shareName;
 
7636
   size_t shareNameLen;
 
7637
   HgfsHeader *packetHeader;
 
7638
   uint32 flags;
 
7639
 
 
7640
   if (HgfsServerGetShareName(sharedFolder, &shareNameLen, &shareName)) {
 
7641
 
 
7642
      sizeNeeded = HgfsPackCalculateNotificationSize(shareName, fileName);
 
7643
 
 
7644
      packetHeader = Util_SafeCalloc(1, sizeNeeded);
 
7645
      packet = Util_SafeCalloc(1, sizeof *packet);
 
7646
      packet->guestInitiated = FALSE;
 
7647
      packet->metaPacketSize = sizeNeeded;
 
7648
      packet->metaPacket = packetHeader;
 
7649
      packet->dataPacketIsAllocated = TRUE;
 
7650
      flags = 0;
 
7651
      if (mask & HGFS_NOTIFY_EVENTS_DROPPED) {
 
7652
         flags |= HGFS_NOTIFY_FLAG_OVERFLOW;
 
7653
      }
 
7654
 
 
7655
      HgfsPackChangeNotificationRequest(packetHeader, subscriber, shareName, fileName, mask,
 
7656
                                        flags, session, &sizeNeeded);
 
7657
      if (!HgfsPacketSend(packet, (char *)packetHeader,  sizeNeeded, session, 0)) {
 
7658
         LOG(4, ("%s: failed to send notification to the host\n", __FUNCTION__));
 
7659
      }
 
7660
 
 
7661
      LOG(4, ("%s: notification for folder: %d index: %d file name %s "
 
7662
              " mask %x\n", __FUNCTION__, sharedFolder,
 
7663
              (int)subscriber, fileName, mask));
 
7664
      free(shareName);
 
7665
   } else {
 
7666
      LOG(4, ("%s: failed to find shared folder for a handle %x\n",
 
7667
              __FUNCTION__, sharedFolder));
 
7668
   }
6846
7669
}
6847
7670
 
6848
7671
 
7056
7879
      printf("\nadding node with name: %s\n", tempName);
7057
7880
      localId.volumeId = 0;
7058
7881
      localId.fileId = i + 1000;
7059
 
      node = HgfsAddNewFileNode(strdup(tempName), &localId);
 
7882
      node = HgfsAddNewFileNode(Util_SafeStrdup(tempName), &localId);
7060
7883
      array[i] = HgfsFileNode2Handle(node);
7061
7884
   }
7062
7885
 
7088
7911
 
7089
7912
      Str_Sprintf(tempName, sizeof tempName, "baseDir%u", i);
7090
7913
      printf("\nadding search with baseDir: \"%s\"\n", tempName);
7091
 
      search = HgfsAddNewSearch(strdup(tempName));
 
7914
      search = HgfsAddNewSearch(Util_SafeStrdup(tempName));
7092
7915
      array[i] = HgfsSearch2SearchHandle(search);
7093
7916
   }
7094
7917