4809
4830
HgfsSessionInfo *session) // IN: Session info
4811
4832
HgfsReplyDestroySessionV4 *reply;
4813
HGFS_ASSERT_PACK_PARAMS;
4817
return HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
4818
(void **)&reply, session);
4835
HGFS_ASSERT_PACK_PARAMS;
4839
result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
4840
(void **)&reply, session);
4842
/* Reply only consists of a reserved field. */
4843
*payloadSize = sizeof *reply;
4844
reply->reserved = 0;
4852
*-----------------------------------------------------------------------------
4854
* HgfsServerGetDefaultCapabilities --
4856
* Returns list capabilities that are supported by all sessions.
4864
*-----------------------------------------------------------------------------
4868
HgfsServerGetDefaultCapabilities(HgfsCapability *capabilities, // OUT: capabilities
4869
uint32 *numberOfCapabilities) // OUT: number of items
4871
*numberOfCapabilities = ARRAYSIZE(hgfsDefaultCapabilityTable);
4872
ASSERT(*numberOfCapabilities <= HGFS_OP_MAX);
4873
memcpy(capabilities, hgfsDefaultCapabilityTable, sizeof hgfsDefaultCapabilityTable);
4878
*-----------------------------------------------------------------------------
4880
* HgfsPackSetWatchReplyV4 --
4882
* Pack hgfs set watch V4 reply payload to the HgfsReplySetWatchV4 structure.
4890
*-----------------------------------------------------------------------------
4894
HgfsPackSetWatchReplyV4(HgfsSubscriberHandle watchId, // IN: host id of thee new watch
4895
HgfsReplySetWatchV4 *reply) // OUT: reply buffer to fill
4897
reply->watchId = watchId;
4898
reply->reserved = 0;
4903
*-----------------------------------------------------------------------------
4905
* HgfsPackSetWatchReply --
4907
* Pack hgfs set watch reply to the HgfsReplySetWatchV4 structure.
4910
* TRUE if successfully allocated reply request, FALSE otherwise.
4915
*-----------------------------------------------------------------------------
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
4927
HgfsReplySetWatchV4 *reply;
4929
HGFS_ASSERT_PACK_PARAMS;
4933
if (HGFS_OP_SET_WATCH_V4 != op) {
4937
result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
4938
(void **)&reply, session);
4940
HgfsPackSetWatchReplyV4(watchId, reply);
4941
*payloadSize = sizeof *reply;
4950
*-----------------------------------------------------------------------------
4952
* HgfsUnpackSetWatchPayloadV4 --
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.
4964
*-----------------------------------------------------------------------------
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
4978
if (payloadSize < sizeof *requestV4) {
4982
*flags = requestV4->flags;
4983
*events = requestV4->events;
4985
return HgfsUnpackFileNameV3(&requestV4->fileName,
4986
payloadSize - sizeof *requestV4,
4996
*-----------------------------------------------------------------------------
4998
* HgfsUnpackSetWatchRequest --
5000
* Unpack hgfs set directory notication watch request and initialize a corresponding
5001
* HgfsHandle or directory name to tell us which directory to monitor.
5010
*-----------------------------------------------------------------------------
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
5025
HgfsRequestSetWatchV4 *requestV4 = (HgfsRequestSetWatchV4 *)packet;
5037
if (HGFS_OP_SET_WATCH_V4 != op) {
5041
result = HgfsUnpackSetWatchPayloadV4(requestV4, packetSize, useHandle, flags,
5042
events, cpName, cpNameSize, dir, caseFlags);
5046
LOG(4, ("%s: Error decoding HGFS packet\n", __FUNCTION__));
5053
*-----------------------------------------------------------------------------
5055
* HgfsPackRemoveWatchReply --
5057
* Pack hgfs remove watch reply to the HgfsReplyRemoveWatchV4 structure.
5060
* TRUE if successfully allocated reply request, FALSE otherwise.
5065
*-----------------------------------------------------------------------------
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
5076
HgfsReplyRemoveWatchV4 *reply;
5078
HGFS_ASSERT_PACK_PARAMS;
5082
if (HGFS_OP_REMOVE_WATCH_V4 != op) {
5086
result = HgfsAllocInitReply(packet, packetHeader, sizeof *reply,
5087
(void **)&reply, session);
5089
reply->reserved = 0;
5090
*payloadSize = sizeof *reply;
5098
*-----------------------------------------------------------------------------
5100
* HgfsUnpackRemoveWatchPayload --
5102
* Unpack HGFS remove directory notication watch payload version 4.
5111
*-----------------------------------------------------------------------------
5115
HgfsUnpackRemoveWatchPayloadV4(HgfsRequestRemoveWatchV4 *requestV4, // IN: request payload
5116
size_t payloadSize, // IN: payload size
5117
HgfsSubscriberHandle *watchId) // OUT: watch id
5119
if (payloadSize < sizeof *requestV4) {
5123
*watchId = requestV4->watchId;
5129
*-----------------------------------------------------------------------------
5131
* HgfsUnpackRemoveWatchRequest --
5133
* Unpack hgfs remove directory notication watch request.
5142
*-----------------------------------------------------------------------------
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
5151
HgfsRequestRemoveWatchV4 *requestV4 = (HgfsRequestRemoveWatchV4 *)packet;
5156
ASSERT(HGFS_OP_REMOVE_WATCH_V4 == op);
5158
if (HGFS_OP_REMOVE_WATCH_V4 != op) {
5160
} else if (!HgfsUnpackRemoveWatchPayloadV4(requestV4, packetSize, watchId)) {
5161
LOG(4, ("%s: Error decoding HGFS packet\n", __FUNCTION__));
5170
*-----------------------------------------------------------------------------
5172
* HgfsPackCalculateNotificationSize --
5174
* Calculates size needed for change notification packet.
5177
* TRUE if successfully allocated reply request, FALSE otherwise.
5182
*-----------------------------------------------------------------------------
5186
HgfsPackCalculateNotificationSize(char const *shareName, // IN: shared folder name
5187
char *fileName) // IN: relative file path
5189
size_t result = sizeof(HgfsRequestNotifyV4);
5191
if (NULL != fileName) {
5192
size_t shareNameLen = strlen(shareName);
5193
result += strlen(fileName) + 1 + shareNameLen;
5195
result += sizeof(HgfsHeader);
5201
*-----------------------------------------------------------------------------
5203
* HgfsBuildCPName --
5205
* Build crossplatform name out of share name and relative to the shared folder
5209
* Length of the output crossplatform name.
5214
*-----------------------------------------------------------------------------
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
5222
size_t shareNameLen = strlen(shareName) + 1;
5223
size_t fileNameLen = strlen(fileName) + 1;
5224
char *fullName = Util_SafeMalloc(shareNameLen + fileNameLen);
5227
*cpName = Util_SafeMalloc(shareNameLen + fileNameLen);
5228
Str_Strcpy(fullName, shareName, shareNameLen);
5229
fullName[shareNameLen - 1] = DIRSEPC;
5230
Str_Strcpy(fullName + shareNameLen, fileName, fileNameLen);
5232
result = CPName_ConvertTo(fullName, shareNameLen + fileNameLen, *cpName);
5233
ASSERT(result > 0); // Unescaped name can't be longer then escaped thus it must fit.
5241
*-----------------------------------------------------------------------------
5243
* HgfsPackHgfsName --
5245
* Pack cpName into HgfsFileName structure.
5248
* TRUE if there is enough space in the buffer,
5254
*-----------------------------------------------------------------------------
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
5264
if (availableSpace < offsetof(HgfsFileName, name) + cpNameLen) {
5267
fileName->length = cpNameLen;
5268
memcpy(fileName->name, cpName, cpNameLen);
5269
*nameSize = offsetof(HgfsFileName, name) + cpNameLen;
5275
*-----------------------------------------------------------------------------
5277
* HgfsPackChangeNotificationV4 --
5279
* Pack single change directory notification event information.
5282
* Length of the packed structure or 0 if the structure does not fit in the
5288
*-----------------------------------------------------------------------------
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
5298
size_t remainingSize;
5299
size_t totalLength = sizeof *reply;
5301
if (sizeof *reply > bufferSize) {
5305
reply->nextOffset = 0;
5307
if (NULL != fileName) {
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;
5322
reply->fileName.length = 0;
5323
totalLength = sizeof *reply;
5330
*-----------------------------------------------------------------------------
5332
* HgfsPackChangeNotifyRequestV4 --
5334
* Pack hgfs directory change notification request to be sent to the guest.
5337
* Length of the packed structure or 0 if the structure does not fit in the
5343
*-----------------------------------------------------------------------------
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
5356
size_t notificationOffset;
5358
if (bufferSize < sizeof *reply) {
5361
reply->watchId = watchId;
5362
reply->flags = flags;
5363
if ((flags & HGFS_NOTIFY_FLAG_OVERFLOW) == HGFS_NOTIFY_FLAG_OVERFLOW) {
5364
size = sizeof *reply;
5366
reply->flags = HGFS_NOTIFY_FLAG_OVERFLOW;
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.
5374
notificationOffset = offsetof(HgfsRequestNotifyV4, events);
5375
size = HgfsPackChangeNotificationV4(mask, shareName, fileName,
5376
bufferSize - notificationOffset,
5379
size += notificationOffset;
5382
* Set event flag to tell guest that some events were dropped
5383
* when filling out notification details failed.
5385
size = sizeof *reply;
5387
reply->flags = HGFS_NOTIFY_FLAG_OVERFLOW;
5395
*-----------------------------------------------------------------------------
5397
* HgfsPackChangeNotificationRequest --
5399
* Pack hgfs directory change notification request to the
5400
* HgfsRequestNotifyV4 structure.
5403
* TRUE if successfully allocated reply request, FALSE otherwise.
5408
*-----------------------------------------------------------------------------
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
5422
HgfsRequestNotifyV4 *reply;
5423
HgfsHeader *header = (HgfsHeader *)packet;
5428
ASSERT(NULL != fileName ||
5429
(flags & HGFS_NOTIFY_FLAG_OVERFLOW) == HGFS_NOTIFY_FLAG_OVERFLOW);
5433
if (*bufferSize < sizeof *header) {
5438
* Initialize notification header.
5439
* Set status and requestId to 0 since these fields are not relevant for
5441
* Initialize payload size to 0 - it is not known yet and will be filled later.
5443
header->headerSize = sizeof *header;
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);
5450
header->packetSize = header->headerSize + size;