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

« back to all changes in this revision

Viewing changes to lib/hgfsServer/hgfsServerParameters.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:
51
51
      ASSERT(payloadSize); \
52
52
   } while(0)
53
53
 
54
 
/* Capabilities of the HGFS server. */
55
 
static HgfsCapability hgfsServerCapabilities[] =
 
54
/*
 
55
 * This is the default/minimal set of capabilities which is supported by every transport.
 
56
 * Every transport and session may have additional capabilities in addition to these.
 
57
 */
 
58
static HgfsCapability hgfsDefaultCapabilityTable[] =
56
59
{
57
60
   {HGFS_OP_OPEN,                  HGFS_REQUEST_SUPPORTED},
58
61
   {HGFS_OP_READ,                  HGFS_REQUEST_SUPPORTED},
97
100
   {HGFS_OP_WRITE_WIN32_STREAM_V3, HGFS_REQUEST_WIN32_SUPPORTED},
98
101
   {HGFS_OP_CREATE_SESSION_V4,     HGFS_REQUEST_SUPPORTED},
99
102
   {HGFS_OP_DESTROY_SESSION_V4,    HGFS_REQUEST_SUPPORTED},
100
 
   {HGFS_OP_READ_FAST_V4,          HGFS_REQUEST_SUPPORTED},
101
 
   {HGFS_OP_WRITE_FAST_V4,         HGFS_REQUEST_SUPPORTED},
 
103
   {HGFS_OP_READ_FAST_V4,          HGFS_REQUEST_NOT_SUPPORTED},
 
104
   {HGFS_OP_WRITE_FAST_V4,         HGFS_REQUEST_NOT_SUPPORTED},
 
105
   {HGFS_OP_SET_WATCH_V4,          HGFS_REQUEST_NOT_SUPPORTED},
 
106
   {HGFS_OP_REMOVE_WATCH_V4,       HGFS_REQUEST_NOT_SUPPORTED},
 
107
   {HGFS_OP_NOTIFY_V4,             HGFS_REQUEST_NOT_SUPPORTED},
102
108
   {HGFS_OP_OPEN_V4,               HGFS_REQUEST_NOT_SUPPORTED},
103
109
   {HGFS_OP_DIRECTORY_READ_V4,     HGFS_REQUEST_NOT_SUPPORTED},
104
110
   {HGFS_OP_ENUMERATE_STREAMS_V4,  HGFS_REQUEST_NOT_SUPPORTED},
116
122
   {HGFS_OP_UNLOCK_BYTE_RANGE_V4,  HGFS_REQUEST_NOT_SUPPORTED},
117
123
   {HGFS_OP_QUERY_EAS_V4,          HGFS_REQUEST_NOT_SUPPORTED},
118
124
   {HGFS_OP_SET_EAS_V4,            HGFS_REQUEST_NOT_SUPPORTED},
119
 
   {HGFS_OP_SET_WATCH_V4,          HGFS_REQUEST_NOT_SUPPORTED},
120
 
   {HGFS_OP_REMOVE_WATCH_V4,       HGFS_REQUEST_NOT_SUPPORTED},
121
 
   {HGFS_OP_NOTIFY_V4,             HGFS_REQUEST_NOT_SUPPORTED},
122
125
};
123
126
 
124
127
/*
355
358
   if (HGFS_ERROR_SUCCESS != result) {
356
359
      LOG(4, ("%s: Malformed HGFS packet received!\n", __FUNCTION__));
357
360
   }
 
361
 
 
362
   localInput->payloadOffset = (char *)localInput->payload -
 
363
                               (char *)localInput->metaPacket;
358
364
   *status = result;
359
365
   return TRUE;
360
366
}
1001
1007
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
1002
1008
                                  (void **)&reply, session);
1003
1009
      if (result) {
 
1010
         /* Reply consists of a reserved field only. */
 
1011
         reply->reserved = 0;
1004
1012
         *payloadSize = sizeof *reply;
1005
1013
      }
1006
1014
      break;
1059
1067
/*
1060
1068
 *-----------------------------------------------------------------------------
1061
1069
 *
1062
 
 * HgfsUnpackClosePayloadV3 --
 
1070
 * HgfsUnpackSearchClosePayloadV3 --
1063
1071
 *
1064
1072
 *    Unpack hgfs search close payload V3 to get the search handle which need to
1065
1073
 *    be closed.
1179
1187
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
1180
1188
                                  (void **)&reply, session);
1181
1189
      if (result) {
 
1190
         /* Reply consists of only a reserved field. */
 
1191
         reply->reserved = 0;
1182
1192
         *payloadSize = sizeof *reply;
1183
1193
      }
1184
1194
      break;
2003
2013
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
2004
2014
                                  (void **)&reply, session);
2005
2015
      if (result) {
 
2016
         /* Reply consists of only a reserved field. */
 
2017
         reply->reserved = 0;
2006
2018
         *payloadSize = sizeof *reply;
2007
2019
      }
2008
2020
      break;
3150
3162
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
3151
3163
                                  (void **)&reply, session);
3152
3164
      if (result) {
 
3165
         /* Reply consists of only a reserved field. */
 
3166
         reply->reserved = 0;
3153
3167
         *payloadSize = sizeof *reply;
3154
3168
      }
3155
3169
      break;
3449
3463
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
3450
3464
                                  (void **)&reply, session);
3451
3465
      if (result) {
 
3466
         /* Reply consists of only a reserved field. */
 
3467
         reply->reserved = 0;
3452
3468
         *payloadSize = sizeof *reply;
3453
3469
      }
3454
3470
      break;
3610
3626
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
3611
3627
                                 (void **)&reply, session);
3612
3628
      if (result) {
 
3629
         reply->reserved = 0;
3613
3630
         reply->actualSize = actualSize;
3614
3631
         *payloadSize = sizeof *reply;
3615
3632
      }
3987
4004
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
3988
4005
                                  (void **)&reply, session);
3989
4006
      if (result) {
 
4007
         reply->reserved = 0;
3990
4008
         reply->actualSize = actualSize;
3991
4009
         *payloadSize = sizeof *reply;
3992
4010
      }
4189
4207
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
4190
4208
                                  (void **)&reply, session);
4191
4209
      if (result) {
 
4210
         reply->reserved = 0;
4192
4211
         reply->freeBytes = freeBytes;
4193
4212
         reply->totalBytes = totalBytes;
4194
4213
         *payloadSize = sizeof *reply;
4432
4451
 
4433
4452
   switch (op) {
4434
4453
   case HGFS_OP_CREATE_SYMLINK_V3: {
4435
 
      HgfsReplyQueryVolumeV3 *reply;
 
4454
      HgfsReplySymlinkCreateV3 *reply;
4436
4455
 
4437
4456
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
4438
4457
                                  (void **)&reply, session);
4439
4458
      if (result) {
 
4459
         /* Reply only consists of a reserved field. */
 
4460
         reply->reserved = 0;
4440
4461
         *payloadSize = sizeof *reply;
4441
4462
      }
4442
4463
      break;
4443
4464
   }
4444
4465
   case HGFS_OP_CREATE_SYMLINK: {
4445
 
      HgfsReplyQueryVolume *reply;
 
4466
      HgfsReplySymlinkCreate *reply;
4446
4467
 
4447
4468
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
4448
4469
                                  (void **)&reply, session);
4632
4653
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
4633
4654
                                  (void **)&reply, session);
4634
4655
      if (result) {
 
4656
         reply->reserved = 0;
4635
4657
         reply->search = search;
4636
4658
         *payloadSize = sizeof *reply;
4637
4659
      }
4763
4785
{
4764
4786
   Bool result;
4765
4787
   HgfsReplyCreateSessionV4 *reply;
4766
 
   uint32 numCapabilities = ARRAYSIZE(hgfsServerCapabilities);
 
4788
   uint32 numCapabilities = session->numberOfCapabilities;
 
4789
   uint32 capabilitiesLen = numCapabilities * sizeof *session->hgfsSessionCapabilities;
4767
4790
 
4768
4791
   HGFS_ASSERT_PACK_PARAMS;
4769
4792
 
4770
 
   *payloadSize = offsetof(HgfsReplyCreateSessionV4, capabilities) +
4771
 
      sizeof hgfsServerCapabilities;
 
4793
   *payloadSize = offsetof(HgfsReplyCreateSessionV4, capabilities) + capabilitiesLen;
4772
4794
 
4773
 
   result = HgfsAllocInitReply(packet, packetHeader, *payloadSize,
4774
 
                               (void **)&reply, session);
 
4795
   result = HgfsAllocInitReply(packet, packetHeader, *payloadSize, (void **)&reply,
 
4796
                               session);
4775
4797
   if (result) {
4776
4798
      reply->sessionId = session->sessionId;
4777
4799
      reply->numCapabilities = numCapabilities;
4778
4800
      reply->maxPacketSize = session->maxPacketSize;
4779
4801
      reply->identityOffset = 0;
4780
4802
      reply->reserved = 0;
4781
 
      memcpy(reply->capabilities, hgfsServerCapabilities,
4782
 
             sizeof hgfsServerCapabilities);
 
4803
      memcpy(reply->capabilities, session->hgfsSessionCapabilities, capabilitiesLen);
4783
4804
   }
4784
4805
 
4785
4806
   return result;
4809
4830
                            HgfsSessionInfo *session)  // IN: Session info
4810
4831
{
4811
4832
   HgfsReplyDestroySessionV4 *reply;
4812
 
 
4813
 
   HGFS_ASSERT_PACK_PARAMS;
4814
 
 
4815
 
   *payloadSize = 0;
4816
 
 
4817
 
   return HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
4818
 
                             (void **)&reply, session);
 
4833
   Bool result;
 
4834
 
 
4835
   HGFS_ASSERT_PACK_PARAMS;
 
4836
 
 
4837
   *payloadSize = 0;
 
4838
 
 
4839
   result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
 
4840
                               (void **)&reply, session);
 
4841
   if (result) {
 
4842
      /* Reply only consists of a reserved field. */
 
4843
      *payloadSize = sizeof *reply;
 
4844
      reply->reserved = 0;
 
4845
   }
 
4846
 
 
4847
   return result;
 
4848
}
 
4849
 
 
4850
 
 
4851
/*
 
4852
 *-----------------------------------------------------------------------------
 
4853
 *
 
4854
 * HgfsServerGetDefaultCapabilities --
 
4855
 *
 
4856
 *    Returns list capabilities that are supported by all sessions.
 
4857
 *
 
4858
 * Results:
 
4859
 *    None
 
4860
 *
 
4861
 * Side effects:
 
4862
 *    None
 
4863
 *
 
4864
 *-----------------------------------------------------------------------------
 
4865
 */
 
4866
 
 
4867
void
 
4868
HgfsServerGetDefaultCapabilities(HgfsCapability *capabilities,  // OUT: capabilities
 
4869
                                 uint32 *numberOfCapabilities)  // OUT: number of items
 
4870
{
 
4871
   *numberOfCapabilities = ARRAYSIZE(hgfsDefaultCapabilityTable);
 
4872
   ASSERT(*numberOfCapabilities <= HGFS_OP_MAX);
 
4873
   memcpy(capabilities, hgfsDefaultCapabilityTable, sizeof hgfsDefaultCapabilityTable);
 
4874
}
 
4875
 
 
4876
 
 
4877
/*
 
4878
 *-----------------------------------------------------------------------------
 
4879
 *
 
4880
 * HgfsPackSetWatchReplyV4 --
 
4881
 *
 
4882
 *    Pack hgfs set watch V4 reply payload to the HgfsReplySetWatchV4 structure.
 
4883
 *
 
4884
 * Results:
 
4885
 *    None.
 
4886
 *
 
4887
 * Side effects:
 
4888
 *    None
 
4889
 *
 
4890
 *-----------------------------------------------------------------------------
 
4891
 */
 
4892
 
 
4893
static void
 
4894
HgfsPackSetWatchReplyV4(HgfsSubscriberHandle watchId, // IN: host id of thee new watch
 
4895
                        HgfsReplySetWatchV4 *reply)   // OUT: reply buffer to fill
 
4896
{
 
4897
   reply->watchId = watchId;
 
4898
   reply->reserved = 0;
 
4899
}
 
4900
 
 
4901
 
 
4902
/*
 
4903
 *-----------------------------------------------------------------------------
 
4904
 *
 
4905
 * HgfsPackSetWatchReply --
 
4906
 *
 
4907
 *    Pack hgfs set watch reply to the HgfsReplySetWatchV4 structure.
 
4908
 *
 
4909
 * Results:
 
4910
 *    TRUE if successfully allocated reply request, FALSE otherwise.
 
4911
 *
 
4912
 * Side effects:
 
4913
 *    None
 
4914
 *
 
4915
 *-----------------------------------------------------------------------------
 
4916
 */
 
4917
 
 
4918
Bool
 
4919
HgfsPackSetWatchReply(HgfsPacket *packet,           // IN/OUT: Hgfs Packet
 
4920
                      char const *packetHeader,     // IN: packet header
 
4921
                      HgfsOp     op,                // IN: operation code
 
4922
                      HgfsSubscriberHandle watchId, // IN: id of the new watch
 
4923
                      size_t *payloadSize,          // OUT: size of packet
 
4924
                      HgfsSessionInfo *session)     // IN: Session info
 
4925
{
 
4926
   Bool result;
 
4927
   HgfsReplySetWatchV4 *reply;
 
4928
 
 
4929
   HGFS_ASSERT_PACK_PARAMS;
 
4930
 
 
4931
   *payloadSize = 0;
 
4932
 
 
4933
   if (HGFS_OP_SET_WATCH_V4 != op) {
 
4934
      NOT_REACHED();
 
4935
      result = FALSE;
 
4936
   } else {
 
4937
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
 
4938
                               (void **)&reply, session);
 
4939
      if (result) {
 
4940
         HgfsPackSetWatchReplyV4(watchId, reply);
 
4941
         *payloadSize = sizeof *reply;
 
4942
      }
 
4943
   }
 
4944
 
 
4945
   return result;
 
4946
}
 
4947
 
 
4948
 
 
4949
/*
 
4950
 *-----------------------------------------------------------------------------
 
4951
 *
 
4952
 * HgfsUnpackSetWatchPayloadV4 --
 
4953
 *
 
4954
 *    Unpack HGFS set directory notication watch payload version 4 and initializes
 
4955
 *    a corresponding HgfsHandle or file name to tell us which directory to watch.
 
4956
 *
 
4957
 * Results:
 
4958
 *    TRUE on success.
 
4959
 *    FALSE on failure.
 
4960
 *
 
4961
 * Side effects:
 
4962
 *    None
 
4963
 *
 
4964
 *-----------------------------------------------------------------------------
 
4965
 */
 
4966
 
 
4967
static Bool
 
4968
HgfsUnpackSetWatchPayloadV4(HgfsRequestSetWatchV4 *requestV4, // IN: request payload
 
4969
                            size_t payloadSize,               // IN: payload size
 
4970
                            Bool *useHandle,                  // OUT: handle or cpName
 
4971
                            uint32 *flags,                    // OUT: watch flags
 
4972
                            uint32 *events,                   // OUT: event filter
 
4973
                            char **cpName,                    // OUT: cpName
 
4974
                            size_t *cpNameSize,               // OUT: cpName size
 
4975
                            HgfsHandle *dir,                  // OUT: directory handle
 
4976
                            uint32 *caseFlags)                // OUT: case-sensitivity
 
4977
{
 
4978
   if (payloadSize < sizeof *requestV4) {
 
4979
      return FALSE;
 
4980
   }
 
4981
 
 
4982
   *flags = requestV4->flags;
 
4983
   *events = requestV4->events;
 
4984
 
 
4985
   return HgfsUnpackFileNameV3(&requestV4->fileName,
 
4986
                               payloadSize - sizeof *requestV4,
 
4987
                               useHandle,
 
4988
                               cpName,
 
4989
                               cpNameSize,
 
4990
                               dir,
 
4991
                               caseFlags);
 
4992
}
 
4993
 
 
4994
 
 
4995
/*
 
4996
 *-----------------------------------------------------------------------------
 
4997
 *
 
4998
 * HgfsUnpackSetWatchRequest --
 
4999
 *
 
5000
 *    Unpack hgfs set directory notication watch request and initialize a corresponding
 
5001
 *    HgfsHandle or directory name to tell us which directory to monitor.
 
5002
 *
 
5003
 * Results:
 
5004
 *    TRUE on success.
 
5005
 *    FALSE on failure.
 
5006
 *
 
5007
 * Side effects:
 
5008
 *    None
 
5009
 *
 
5010
 *-----------------------------------------------------------------------------
 
5011
 */
 
5012
 
 
5013
Bool
 
5014
HgfsUnpackSetWatchRequest(void const *packet,      // IN: HGFS packet
 
5015
                          size_t packetSize,       // IN: request packet size
 
5016
                          HgfsOp op,               // IN: requested operation
 
5017
                          Bool *useHandle,         // OUT: handle or cpName
 
5018
                          char **cpName,           // OUT: cpName
 
5019
                          size_t *cpNameSize,      // OUT: cpName size
 
5020
                          uint32 *flags,           // OUT: flags for the new watch
 
5021
                          uint32 *events,          // OUT: event filter
 
5022
                          HgfsHandle *dir,         // OUT: direrctory handle
 
5023
                          uint32 *caseFlags)       // OUT: case-sensitivity flags
 
5024
{
 
5025
   HgfsRequestSetWatchV4 *requestV4 = (HgfsRequestSetWatchV4 *)packet;
 
5026
   Bool result;
 
5027
 
 
5028
   ASSERT(packet);
 
5029
   ASSERT(cpName);
 
5030
   ASSERT(cpNameSize);
 
5031
   ASSERT(dir);
 
5032
   ASSERT(flags);
 
5033
   ASSERT(events);
 
5034
   ASSERT(caseFlags);
 
5035
   ASSERT(useHandle);
 
5036
 
 
5037
   if (HGFS_OP_SET_WATCH_V4 != op) {
 
5038
      NOT_REACHED();
 
5039
      result = FALSE;
 
5040
   } else {
 
5041
      result = HgfsUnpackSetWatchPayloadV4(requestV4, packetSize, useHandle, flags,
 
5042
                                           events, cpName, cpNameSize, dir, caseFlags);
 
5043
   }
 
5044
 
 
5045
   if (!result) {
 
5046
      LOG(4, ("%s: Error decoding HGFS packet\n", __FUNCTION__));
 
5047
   }
 
5048
   return result;
 
5049
}
 
5050
 
 
5051
 
 
5052
/*
 
5053
 *-----------------------------------------------------------------------------
 
5054
 *
 
5055
 * HgfsPackRemoveWatchReply --
 
5056
 *
 
5057
 *    Pack hgfs remove watch reply to the HgfsReplyRemoveWatchV4 structure.
 
5058
 *
 
5059
 * Results:
 
5060
 *    TRUE if successfully allocated reply request, FALSE otherwise.
 
5061
 *
 
5062
 * Side effects:
 
5063
 *    None
 
5064
 *
 
5065
 *-----------------------------------------------------------------------------
 
5066
 */
 
5067
 
 
5068
Bool
 
5069
HgfsPackRemoveWatchReply(HgfsPacket *packet,           // IN/OUT: Hgfs Packet
 
5070
                         char const *packetHeader,     // IN: packet header
 
5071
                         HgfsOp     op,                // IN: operation code
 
5072
                         size_t *payloadSize,          // OUT: size of packet
 
5073
                         HgfsSessionInfo *session)     // IN: Session info
 
5074
{
 
5075
   Bool result;
 
5076
   HgfsReplyRemoveWatchV4 *reply;
 
5077
 
 
5078
   HGFS_ASSERT_PACK_PARAMS;
 
5079
 
 
5080
   *payloadSize = 0;
 
5081
 
 
5082
   if (HGFS_OP_REMOVE_WATCH_V4 != op) {
 
5083
      NOT_REACHED();
 
5084
      result = FALSE;
 
5085
   } else {
 
5086
      result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
 
5087
                                  (void **)&reply, session);
 
5088
      if (result) {
 
5089
         reply->reserved = 0;
 
5090
         *payloadSize = sizeof *reply;
 
5091
      }
 
5092
   }
 
5093
   return result;
 
5094
}
 
5095
 
 
5096
 
 
5097
/*
 
5098
 *-----------------------------------------------------------------------------
 
5099
 *
 
5100
 * HgfsUnpackRemoveWatchPayload --
 
5101
 *
 
5102
 *    Unpack HGFS remove directory notication watch payload version 4.
 
5103
 *
 
5104
 * Results:
 
5105
 *    TRUE on success.
 
5106
 *    FALSE on failure.
 
5107
 *
 
5108
 * Side effects:
 
5109
 *    None
 
5110
 *
 
5111
 *-----------------------------------------------------------------------------
 
5112
 */
 
5113
 
 
5114
static Bool
 
5115
HgfsUnpackRemoveWatchPayloadV4(HgfsRequestRemoveWatchV4 *requestV4, // IN: request payload
 
5116
                               size_t payloadSize,                  // IN: payload size
 
5117
                               HgfsSubscriberHandle *watchId)       // OUT: watch id
 
5118
{
 
5119
   if (payloadSize < sizeof *requestV4) {
 
5120
      return FALSE;
 
5121
   }
 
5122
 
 
5123
   *watchId = requestV4->watchId;
 
5124
   return TRUE;
 
5125
}
 
5126
 
 
5127
 
 
5128
/*
 
5129
 *-----------------------------------------------------------------------------
 
5130
 *
 
5131
 * HgfsUnpackRemoveWatchRequest --
 
5132
 *
 
5133
 *    Unpack hgfs remove directory notication watch request.
 
5134
 *
 
5135
 * Results:
 
5136
 *    TRUE on success.
 
5137
 *    FALSE on failure.
 
5138
 *
 
5139
 * Side effects:
 
5140
 *    None
 
5141
 *
 
5142
 *-----------------------------------------------------------------------------
 
5143
 */
 
5144
 
 
5145
Bool
 
5146
HgfsUnpackRemoveWatchRequest(void const *packet,            // IN: HGFS packet
 
5147
                             size_t packetSize,             // IN: request packet size
 
5148
                             HgfsOp op,                     // IN: requested operation
 
5149
                             HgfsSubscriberHandle *watchId) // OUT: watch Id to remove
 
5150
{
 
5151
   HgfsRequestRemoveWatchV4 *requestV4 = (HgfsRequestRemoveWatchV4 *)packet;
 
5152
 
 
5153
   ASSERT(packet);
 
5154
   ASSERT(watchId);
 
5155
 
 
5156
   ASSERT(HGFS_OP_REMOVE_WATCH_V4 == op);
 
5157
 
 
5158
   if (HGFS_OP_REMOVE_WATCH_V4 != op) {
 
5159
      return FALSE;
 
5160
   } else if (!HgfsUnpackRemoveWatchPayloadV4(requestV4, packetSize, watchId)) {
 
5161
      LOG(4, ("%s: Error decoding HGFS packet\n", __FUNCTION__));
 
5162
      return FALSE;
 
5163
   }
 
5164
 
 
5165
   return TRUE;
 
5166
}
 
5167
 
 
5168
 
 
5169
/*
 
5170
 *-----------------------------------------------------------------------------
 
5171
 *
 
5172
 * HgfsPackCalculateNotificationSize --
 
5173
 *
 
5174
 *    Calculates size needed for change notification packet.
 
5175
 *
 
5176
 * Results:
 
5177
 *    TRUE if successfully allocated reply request, FALSE otherwise.
 
5178
 *
 
5179
 * Side effects:
 
5180
 *    None
 
5181
 *
 
5182
 *-----------------------------------------------------------------------------
 
5183
 */
 
5184
 
 
5185
size_t
 
5186
HgfsPackCalculateNotificationSize(char const *shareName, // IN: shared folder name
 
5187
                                  char *fileName)        // IN: relative file path
 
5188
{
 
5189
   size_t result = sizeof(HgfsRequestNotifyV4);
 
5190
 
 
5191
   if (NULL != fileName) {
 
5192
      size_t shareNameLen = strlen(shareName);
 
5193
      result += strlen(fileName) + 1 + shareNameLen;
 
5194
   }
 
5195
   result += sizeof(HgfsHeader);
 
5196
   return result;
 
5197
}
 
5198
 
 
5199
 
 
5200
/*
 
5201
 *-----------------------------------------------------------------------------
 
5202
 *
 
5203
 * HgfsBuildCPName --
 
5204
 *
 
5205
 *    Build crossplatform name out of share name and relative to the shared folder
 
5206
 *    file path.
 
5207
 *
 
5208
 * Results:
 
5209
 *    Length of the output crossplatform name.
 
5210
 *
 
5211
 * Side effects:
 
5212
 *    None
 
5213
 *
 
5214
 *-----------------------------------------------------------------------------
 
5215
 */
 
5216
 
 
5217
static size_t
 
5218
HgfsBuildCPName(char const *shareName,  // IN: utf8 share name
 
5219
                char *fileName,         // IN: utf8 file path
 
5220
                char **cpName)          // OUT: full name in cp format
 
5221
{
 
5222
   size_t shareNameLen = strlen(shareName) + 1;
 
5223
   size_t fileNameLen = strlen(fileName) + 1;
 
5224
   char *fullName = Util_SafeMalloc(shareNameLen + fileNameLen);
 
5225
   size_t result;
 
5226
 
 
5227
   *cpName = Util_SafeMalloc(shareNameLen + fileNameLen);
 
5228
   Str_Strcpy(fullName, shareName, shareNameLen);
 
5229
   fullName[shareNameLen - 1] = DIRSEPC;
 
5230
   Str_Strcpy(fullName + shareNameLen, fileName, fileNameLen);
 
5231
 
 
5232
   result = CPName_ConvertTo(fullName, shareNameLen + fileNameLen, *cpName);
 
5233
   ASSERT(result > 0); // Unescaped name can't be longer then escaped thus it must fit.
 
5234
   free(fullName);
 
5235
 
 
5236
   return result;
 
5237
}
 
5238
 
 
5239
 
 
5240
/*
 
5241
 *-----------------------------------------------------------------------------
 
5242
 *
 
5243
 * HgfsPackHgfsName --
 
5244
 *
 
5245
 *    Pack cpName into HgfsFileName structure.
 
5246
 *
 
5247
 * Results:
 
5248
 *    TRUE if there is enough space in the buffer,
 
5249
 *    FALSE otherwise.
 
5250
 *
 
5251
 * Side effects:
 
5252
 *    None
 
5253
 *
 
5254
 *-----------------------------------------------------------------------------
 
5255
 */
 
5256
 
 
5257
static Bool
 
5258
HgfsPackHgfsName(char *cpName,            // IN: cpName to pack
 
5259
                 size_t cpNameLen,        // IN: length of the cpName
 
5260
                 size_t availableSpace,   // IN: space available for HgfsFileName
 
5261
                 size_t *nameSize,        // OUT: space consumed by HgfsFileName
 
5262
                 HgfsFileName *fileName)  // OUT: structure to pack cpName into
 
5263
{
 
5264
   if (availableSpace < offsetof(HgfsFileName, name) + cpNameLen) {
 
5265
      return FALSE;
 
5266
   }
 
5267
   fileName->length = cpNameLen;
 
5268
   memcpy(fileName->name, cpName, cpNameLen);
 
5269
   *nameSize = offsetof(HgfsFileName, name) + cpNameLen;
 
5270
   return TRUE;
 
5271
}
 
5272
 
 
5273
 
 
5274
/*
 
5275
 *-----------------------------------------------------------------------------
 
5276
 *
 
5277
 * HgfsPackChangeNotificationV4 --
 
5278
 *
 
5279
 *    Pack single change directory notification event information.
 
5280
 *
 
5281
 * Results:
 
5282
 *    Length of the packed structure or 0 if the structure does not fit in the
 
5283
 *    the buffer.
 
5284
 *
 
5285
 * Side effects:
 
5286
 *    None
 
5287
 *
 
5288
 *-----------------------------------------------------------------------------
 
5289
 */
 
5290
 
 
5291
static size_t
 
5292
HgfsPackChangeNotificationV4(uint32 mask,              // IN: event mask
 
5293
                             char const *shareName,    // IN: share name
 
5294
                             char *fileName,           // IN: file name
 
5295
                             size_t bufferSize,        // IN: available space
 
5296
                             HgfsNotifyEventV4 *reply) // OUT: notificaiton buffer
 
5297
{
 
5298
   size_t remainingSize;
 
5299
   size_t totalLength = sizeof *reply;
 
5300
 
 
5301
   if (sizeof *reply > bufferSize) {
 
5302
      return 0;
 
5303
   }
 
5304
 
 
5305
   reply->nextOffset = 0;
 
5306
   reply->mask = mask;
 
5307
   if (NULL != fileName) {
 
5308
      char *fullPath;
 
5309
      size_t nameSize;
 
5310
 
 
5311
      nameSize = HgfsBuildCPName(shareName, fileName, &fullPath);
 
5312
      remainingSize = bufferSize - offsetof(HgfsNotifyEventV4, fileName);
 
5313
      if (HgfsPackHgfsName(fullPath, nameSize, remainingSize, &nameSize,
 
5314
                           &reply->fileName)) {
 
5315
          remainingSize -= nameSize;
 
5316
          totalLength += nameSize;
 
5317
      } else {
 
5318
         totalLength = 0;
 
5319
      }
 
5320
      free(fullPath);
 
5321
   } else {
 
5322
      reply->fileName.length = 0;
 
5323
      totalLength = sizeof *reply;
 
5324
   }
 
5325
   return totalLength;
 
5326
}
 
5327
 
 
5328
 
 
5329
/*
 
5330
 *-----------------------------------------------------------------------------
 
5331
 *
 
5332
 * HgfsPackChangeNotifyRequestV4 --
 
5333
 *
 
5334
 *    Pack hgfs directory change notification request to be sent to the guest.
 
5335
 *
 
5336
 * Results:
 
5337
 *    Length of the packed structure or 0 if the structure does not fit in the
 
5338
 *    the buffer.
 
5339
 *
 
5340
 * Side effects:
 
5341
 *    None
 
5342
 *
 
5343
 *-----------------------------------------------------------------------------
 
5344
 */
 
5345
 
 
5346
static size_t
 
5347
HgfsPackChangeNotifyRequestV4(HgfsSubscriberHandle watchId,  // IN: watch
 
5348
                              uint32 flags,                  // IN: notify flags
 
5349
                              uint32 mask,                   // IN: event mask
 
5350
                              char const *shareName,         // IN: share name
 
5351
                              char *fileName,                // IN: relative file path
 
5352
                              size_t bufferSize,             // IN: available space
 
5353
                              HgfsRequestNotifyV4 *reply)    // OUT: notification buffer
 
5354
{
 
5355
   size_t size;
 
5356
   size_t notificationOffset;
 
5357
 
 
5358
   if (bufferSize < sizeof *reply) {
 
5359
      return 0;
 
5360
   }
 
5361
   reply->watchId = watchId;
 
5362
   reply->flags = flags;
 
5363
   if ((flags & HGFS_NOTIFY_FLAG_OVERFLOW) == HGFS_NOTIFY_FLAG_OVERFLOW) {
 
5364
      size = sizeof *reply;
 
5365
      reply->count = 0;
 
5366
      reply->flags = HGFS_NOTIFY_FLAG_OVERFLOW;
 
5367
   } else {
 
5368
      /*
 
5369
       * For the moment server sends only one notification at a time and it relies
 
5370
       * on transport to coalesce requests.
 
5371
       * Later on we may consider supporting multiple notifications.
 
5372
       */
 
5373
      reply->count = 1;
 
5374
      notificationOffset = offsetof(HgfsRequestNotifyV4, events);
 
5375
      size = HgfsPackChangeNotificationV4(mask, shareName, fileName,
 
5376
                                          bufferSize - notificationOffset,
 
5377
                                          reply->events);
 
5378
      if (size != 0) {
 
5379
         size += notificationOffset;
 
5380
      } else {
 
5381
         /*
 
5382
         * Set event flag to tell guest that some events were dropped
 
5383
         * when filling out notification details failed.
 
5384
         */
 
5385
         size = sizeof *reply;
 
5386
         reply->count = 0;
 
5387
         reply->flags = HGFS_NOTIFY_FLAG_OVERFLOW;
 
5388
      }
 
5389
   }
 
5390
   return size;
 
5391
}
 
5392
 
 
5393
 
 
5394
/*
 
5395
 *-----------------------------------------------------------------------------
 
5396
 *
 
5397
 * HgfsPackChangeNotificationRequest --
 
5398
 *
 
5399
 *    Pack hgfs directory change notification request to the
 
5400
 *    HgfsRequestNotifyV4 structure.
 
5401
 *
 
5402
 * Results:
 
5403
 *    TRUE if successfully allocated reply request, FALSE otherwise.
 
5404
 *
 
5405
 * Side effects:
 
5406
 *    None
 
5407
 *
 
5408
 *-----------------------------------------------------------------------------
 
5409
 */
 
5410
 
 
5411
Bool
 
5412
HgfsPackChangeNotificationRequest(void *packet,                    // IN/OUT: Hgfs Packet
 
5413
                                  HgfsSubscriberHandle subscriber, // IN: watch
 
5414
                                  char const *shareName,           // IN: share name
 
5415
                                  char *fileName,                  // IN: relative name
 
5416
                                  uint32 mask,                     // IN: event mask
 
5417
                                  uint32 flags,                    // IN: notify flags
 
5418
                                  HgfsSessionInfo *session,        // IN: session
 
5419
                                  size_t *bufferSize)              // INOUT: size of packet
 
5420
{
 
5421
   size_t size;
 
5422
   HgfsRequestNotifyV4 *reply;
 
5423
   HgfsHeader *header = (HgfsHeader *)packet;
 
5424
   Bool result;
 
5425
 
 
5426
   ASSERT(packet);
 
5427
   ASSERT(shareName);
 
5428
   ASSERT(NULL != fileName ||
 
5429
          (flags & HGFS_NOTIFY_FLAG_OVERFLOW) == HGFS_NOTIFY_FLAG_OVERFLOW);
 
5430
   ASSERT(session);
 
5431
   ASSERT(bufferSize);
 
5432
 
 
5433
   if (*bufferSize < sizeof *header) {
 
5434
      return FALSE;
 
5435
   }
 
5436
 
 
5437
   /*
 
5438
    *  Initialize notification header.
 
5439
    *  Set status and requestId to 0 since these fields are not relevant for
 
5440
    *  notifications.
 
5441
    *  Initialize payload size to 0 - it is not known yet and will be filled later.
 
5442
    */
 
5443
   header->headerSize = sizeof *header;
 
5444
 
 
5445
   HgfsPackReplyHeaderV4(0, 0, HGFS_OP_NOTIFY_V4, session->sessionId, 0, header);
 
5446
   reply = (HgfsRequestNotifyV4 *)((char *)header + header->headerSize);
 
5447
   size = HgfsPackChangeNotifyRequestV4(subscriber, flags, mask, shareName, fileName,
 
5448
                                        *bufferSize - header->headerSize, reply);
 
5449
   if (0 != size) {
 
5450
      header->packetSize = header->headerSize + size;
 
5451
      result = TRUE;
 
5452
   } else {
 
5453
      result = FALSE;
 
5454
   }
 
5455
 
 
5456
   return result;
4819
5457
}