5196
4670
request->op > HGFS_OP_RENAME_V2) {
5197
4671
headerSize = sizeof(HgfsReply);
5199
replyPacketSize = *packetSize = headerSize + payloadSize;
5200
*packetOut = HSPU_GetReplyPacket(packet, &replyPacketSize, session);
5201
HGFS_REPLYPKT_CHECK(packetOut, *packetSize, replyPacketSize, dummyStatus, exit);
5203
*payload = *packetOut + headerSize;
5204
if (HGFS_V4_LEGACY_OPCODE == request->op) {
5205
HgfsPackReplyHeaderV4(status,
5207
(HgfsHeader const *)packetIn,
5208
(HgfsHeader *)*packetOut);
5209
} else if (request->op < HGFS_OP_CREATE_SESSION_V4) {
5210
HgfsRequest const *request = (HgfsRequest const *)packetIn;
5211
HgfsPackLegacyReplyHeader(status, request->id, (HgfsReply *)*packetOut);
5221
*-----------------------------------------------------------------------------
5223
* HgfsPackOpenReply --
5225
* Pack hgfs open reply to the HgfsReplyOpen{V2} structure.
5233
*-----------------------------------------------------------------------------
5237
HgfsPackOpenReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
5238
char const *packetIn, // IN: incoming packet
5239
HgfsInternalStatus status, // IN: reply status
5240
HgfsFileOpenInfo *openInfo, // IN: open info struct
5241
char **packetOut, // OUT: outgoing packet
5242
size_t *packetSize, // OUT: size of packet
5243
HgfsSessionInfo *session) // IN: Session info
5253
switch (openInfo->requestType) {
5254
case HGFS_OP_OPEN_V3: {
5255
HgfsReplyOpenV3 *reply;
5257
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5258
(void **)&reply, packetSize, session);
5259
if (result == FALSE) {
5262
HgfsPackOpenReplyV3(openInfo, reply);
5265
case HGFS_OP_OPEN_V2: {
5266
HgfsReplyOpenV2 *reply;
5268
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5269
(void **)&reply, packetSize, session);
5270
if (result == FALSE) {
5273
HgfsPackOpenV2Reply(openInfo, reply);
5276
case HGFS_OP_OPEN: {
5277
HgfsReplyOpen *reply;
5279
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5280
(void **)&reply, packetSize, session);
5281
if (result == FALSE) {
5284
HgfsPackOpenV1Reply(openInfo, reply);
5298
*-----------------------------------------------------------------------------
5300
* HgfsUnpackClosePayload --
5302
* Unpack hgfs close payload to get the handle which need to be closed.
5311
*-----------------------------------------------------------------------------
5315
HgfsUnpackClosePayload(HgfsRequestClose *request, // IN: payload
5316
size_t payloadSize, // IN: payload size
5317
HgfsHandle* file) // OUT: HGFS handle to close
5319
LOG(4, ("%s: HGFS_OP_CLOSE\n", __FUNCTION__));
5320
if (payloadSize >= sizeof *request) {
5321
*file = request->file;
5329
*-----------------------------------------------------------------------------
5331
* HgfsUnpackClosePayloadV3 --
5333
* Unpack hgfs close payload V3 to get the handle which need to be closed.
5342
*-----------------------------------------------------------------------------
5346
HgfsUnpackClosePayloadV3(HgfsRequestCloseV3 *requestV3, // IN: payload
5347
size_t payloadSize, // IN: payload size
5348
HgfsHandle* file) // OUT: HGFS handle to close
5350
LOG(4, ("%s: HGFS_OP_CLOSE_V3\n", __FUNCTION__));
5351
if (payloadSize >= sizeof *requestV3) {
5352
*file = requestV3->file;
5360
*-----------------------------------------------------------------------------
5362
* HgfsUnpackCloseRequest --
5364
* Unpack hgfs close request to get the handle to close.
5373
*-----------------------------------------------------------------------------
5377
HgfsUnpackCloseRequest(char const *packetIn, // IN: request packet
5378
size_t packetSize, // IN: request packet size
5379
HgfsOp *op, // OUT: request type
5380
HgfsHandle *file) // OUT: Handle to close
5382
void const *payload;
5387
if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
5392
case HGFS_OP_CLOSE_V3: {
5393
HgfsRequestCloseV3 *requestV3 = (HgfsRequestCloseV3 *)payload;
5395
if (!HgfsUnpackClosePayloadV3(requestV3, payloadSize, file)) {
5400
case HGFS_OP_CLOSE: {
5401
HgfsRequestClose *requestV1 = (HgfsRequestClose *)payload;
5403
if (!HgfsUnpackClosePayload(requestV1, payloadSize, file)) {
5418
*-----------------------------------------------------------------------------
5420
* HgfsPackCloseReply --
5422
* Pack hgfs close reply to the HgfsReplyClose(V3) structure.
5425
* TRUE on success, FALSE on failure
5430
*-----------------------------------------------------------------------------
5434
HgfsPackCloseReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
5435
char const *packetIn, // IN: incoming packet
5436
HgfsInternalStatus status, // IN: reply status
5437
HgfsOp op, // IN: request type
5438
char **packetOut, // OUT: outgoing packet
5439
size_t *packetSize, // OUT: size of packet
5440
HgfsSessionInfo *session) // IN: Session Info
5450
case HGFS_OP_CLOSE_V3: {
5451
HgfsReplyCloseV3 *reply;
5453
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5454
(void **)&reply, packetSize, session);
5457
case HGFS_OP_CLOSE: {
5458
HgfsReplyClose *reply;
5460
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5461
(void **)&reply, packetSize, session);
5474
*-----------------------------------------------------------------------------
5476
* HgfsUnpackSearchClosePayload --
5478
* Unpack hgfs search close payload to get the search handle which need to be closed.
5487
*-----------------------------------------------------------------------------
5491
HgfsUnpackSearchClosePayload(HgfsRequestSearchClose *request, // IN: payload
5492
size_t payloadSize, // IN: payload size
5493
HgfsHandle* search) // OUT: search to close
5495
LOG(4, ("%s: HGFS_OP_SEARCH_CLOSE\n", __FUNCTION__));
5496
if (payloadSize >= sizeof *request) {
5497
*search = request->search;
5505
*-----------------------------------------------------------------------------
5507
* HgfsUnpackClosePayloadV3 --
5509
* Unpack hgfs search close payload V3 to get the search handle which need to
5519
*-----------------------------------------------------------------------------
5523
HgfsUnpackSearchClosePayloadV3(HgfsRequestSearchCloseV3 *requestV3, // IN: payload
5524
size_t payloadSize, // IN: payload size
5525
HgfsHandle* search) // OUT: search
5527
LOG(4, ("%s: HGFS_OP_SEARCH_CLOSE_V3\n", __FUNCTION__));
5528
if (payloadSize >= sizeof *requestV3) {
5529
*search = requestV3->search;
5537
*-----------------------------------------------------------------------------
5539
* HgfsUnpackSearchCloseRequest --
5541
* Unpack hgfs search close request to get the search handle.
5550
*-----------------------------------------------------------------------------
5554
HgfsUnpackSearchCloseRequest(char const *packetIn, // IN: request packet
5555
size_t packetSize, // IN: request packet size
5556
HgfsOp *op, // OUT: request type
5557
HgfsHandle *search) // OUT: search to close
5559
void const *payload;
5564
if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
5569
case HGFS_OP_SEARCH_CLOSE_V3: {
5570
HgfsRequestSearchCloseV3 *requestV3 = (HgfsRequestSearchCloseV3 *)payload;
5572
if (!HgfsUnpackSearchClosePayloadV3(requestV3, payloadSize, search)) {
5577
case HGFS_OP_SEARCH_CLOSE: {
5578
HgfsRequestSearchClose *requestV1 = (HgfsRequestSearchClose *)payload;
5580
if (!HgfsUnpackSearchClosePayload(requestV1, payloadSize, search)) {
5595
*-----------------------------------------------------------------------------
5597
* HgfsPackSearchCloseReply --
5599
* Pack hgfs SearchClose reply into a HgfsReplySearchClose(V3) structure.
5602
* TRUE on success, FALSE on failure.
5607
*-----------------------------------------------------------------------------
5611
HgfsPackSearchCloseReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
5612
char const *packetIn, // IN: incoming packet
5613
HgfsInternalStatus status, // IN: reply status
5614
HgfsOp op, // IN: request type
5615
char **packetOut, // OUT: outgoing packet
5616
size_t *packetSize, // OUT: size of packet
5617
HgfsSessionInfo *session) // IN: Session Info
5627
case HGFS_OP_SEARCH_CLOSE_V3: {
5628
HgfsReplyCloseV3 *reply;
5630
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5631
(void **)&reply, packetSize, session);
5634
case HGFS_OP_SEARCH_CLOSE: {
5635
HgfsReplyClose *reply;
5637
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5638
(void **)&reply, packetSize, session);
5651
*-----------------------------------------------------------------------------
5653
* HgfsUnpackFileName --
5655
* Unpack HgfsFileName into a pointer to a CPName and size of the name.
5656
* Verifies that input buffer has enough space to hold the name.
5659
* TRUE on success, FALSE on failure (buffer too small).
5664
*-----------------------------------------------------------------------------
5668
HgfsUnpackFileName(HgfsFileName *name, // IN: file name
5669
size_t maxNameSize, // IN: space allocated for the name
5670
char **cpName, // OUT: CP name
5671
size_t *cpNameSize) // OUT: CP name size
5674
* The request file name length is user-provided, so this test must be
5675
* carefully written to prevent wraparounds.
5677
if (name->length > maxNameSize) {
5678
/* The input packet is smaller than the request. */
5681
*cpName = name->name;
5682
*cpNameSize = name->length;
5688
*-----------------------------------------------------------------------------
5690
* HgfsUnpackFileNameV3 --
5692
* Unpack HgfsFileNameV3 into a pointer to a CPName and size of the name
5693
* or into file handle.
5694
* Verifies that input buffer has enough space to hold the name.
5697
* TRUE on success, FALSE on failure (buffer too small).
5702
*-----------------------------------------------------------------------------
5706
HgfsUnpackFileNameV3(HgfsFileNameV3 *name, // IN: file name
5707
size_t maxNameSize, // IN: space allocated for the name
5708
Bool *useHandle, // OUT: file name or handle returned?
5709
char **cpName, // OUT: CP name
5710
size_t *cpNameSize, // OUT: CP name size
5711
HgfsHandle *file, // OUT: HGFS file handle
5712
uint32 *caseFlags) // OUT: case-sensitivity flags
5715
* If we've been asked to reuse a handle, we don't need to look at, let
5716
* alone test the filename or its length.
5718
if (name->flags & HGFS_FILE_NAME_USE_FILE_DESC) {
5722
*caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
5726
* The request file name length is user-provided, so this test must be
5727
* carefully written to prevent wraparounds.
5729
if (name->length > maxNameSize) {
5730
/* The input packet is smaller than the request */
5733
*file = HGFS_INVALID_HANDLE;
5734
*cpName = name->name;
5735
*cpNameSize = name->length;
5736
*caseFlags = name->caseType;
5744
*-----------------------------------------------------------------------------
5746
* HgfsUnpackDeletePayloadV3 --
5748
* Unpack hgfs delete request V3 payload and initialize a corresponding
5749
* HgfsHandle or file name to tell us which to delete. Hints
5750
* holds flags to specify a handle or name for the file or
5751
* directory to delete.
5753
* Since the structure of the get delete request packet is the same
5754
* for Delete File or Directory of the protocol, code is identical for
5764
*-----------------------------------------------------------------------------
5768
HgfsUnpackDeletePayloadV3(HgfsRequestDeleteV3 *requestV3, // IN: request payload
5769
size_t payloadSize, // IN: payload size
5770
char **cpName, // OUT: cpName
5771
size_t *cpNameSize, // OUT: cpName size
5772
HgfsDeleteHint *hints, // OUT: delete hints
5773
HgfsHandle *file, // OUT: file handle
5774
uint32 *caseFlags) // OUT: case-sensitivity flags
5779
if (payloadSize < sizeof *requestV3) {
5783
*hints = requestV3->hints;
5785
result = HgfsUnpackFileNameV3(&requestV3->fileName,
5786
payloadSize - sizeof *requestV3,
5793
*hints |= HGFS_DELETE_HINT_USE_FILE_DESC;
5801
*-----------------------------------------------------------------------------
5803
* HgfsUnpackDeletePayloadV2 --
5805
* Unpack hgfs delete request V2 payload and initialize a corresponding
5806
* HgfsHandle or file name to tell us which to delete. Hints
5807
* holds flags to specify a handle or name for the file or
5808
* directory to delete.
5810
* Since the structure of the get delete request packet is the same
5811
* for Delete File or Directory of the protocol, code is identical for
5821
*-----------------------------------------------------------------------------
5825
HgfsUnpackDeletePayloadV2(HgfsRequestDeleteV2 *requestV2, // IN: request payload
5826
size_t payloadSize, // IN: payload size
5827
char **cpName, // OUT: cpName
5828
size_t *cpNameSize, // OUT: cpName size
5829
HgfsDeleteHint *hints, // OUT: delete hints
5830
HgfsHandle *file) // OUT: file handle
5834
/* Enforced by the dispatch function. */
5835
ASSERT(payloadSize >= sizeof *requestV2);
5837
*file = HGFS_INVALID_HANDLE;
5838
*hints = requestV2->hints;
5841
* If we've been asked to reuse a handle, we don't need to look at, let
5842
* alone test the filename or its length.
5845
if (requestV2->hints & HGFS_DELETE_HINT_USE_FILE_DESC) {
5846
*file = requestV2->file;
5850
result = HgfsUnpackFileName(&requestV2->fileName,
5851
payloadSize - sizeof *requestV2,
5860
*-----------------------------------------------------------------------------
5862
* HgfsUnpackDeletePayloadV1 --
5864
* Unpack hgfs delete request V1 payload and initialize a corresponding
5865
* file name to tell us which to delete.
5867
* Since the structure of the get delete request packet is the same
5868
* for Delete File or Directory of the protocol, code is identical for
5878
*-----------------------------------------------------------------------------
5882
HgfsUnpackDeletePayloadV1(HgfsRequestDelete *requestV1, // IN: request payload
5883
size_t payloadSize, // IN: payload size
5884
char **cpName, // OUT: cpName
5885
size_t *cpNameSize) // OUT: cpName size
5887
return HgfsUnpackFileName(&requestV1->fileName,
5888
payloadSize - sizeof *requestV1,
5895
*-----------------------------------------------------------------------------
5897
* HgfsUnpackDeleteRequest --
5899
* Unpack hgfs delete request and initialize a corresponding
5900
* HgfsHandle or file name to tell us which to delete. Hints
5901
* holds flags to specify a handle or name for the file or
5902
* directory to delete.
5904
* Since the structure of the get delete request packet is the same
5905
* for Delete File or Directory of the protocol, code is identical for
5915
*-----------------------------------------------------------------------------
5919
HgfsUnpackDeleteRequest(char const *packetIn, // IN: request packet
5920
size_t packetSize, // IN: request packet size
5921
HgfsOp *op, // OUT: requested operation
5922
char **cpName, // OUT: cpName
5923
size_t *cpNameSize, // OUT: cpName size
5924
HgfsDeleteHint *hints, // OUT: delete hints
5925
HgfsHandle *file, // OUT: file handle
5926
uint32 *caseFlags) // OUT: case-sensitivity flags
5928
void const *payload;
5938
if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
5942
*caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
5944
*file = HGFS_INVALID_HANDLE;
5947
case HGFS_OP_DELETE_FILE_V3:
5948
case HGFS_OP_DELETE_DIR_V3: {
5949
HgfsRequestDeleteV3 *requestV3 = (HgfsRequestDeleteV3 *)payload;
5951
if (!HgfsUnpackDeletePayloadV3(requestV3,
5962
case HGFS_OP_DELETE_FILE_V2:
5963
case HGFS_OP_DELETE_DIR_V2: {
5964
HgfsRequestDeleteV2 *requestV2 = (HgfsRequestDeleteV2 *)payload;
5966
if (!HgfsUnpackDeletePayloadV2(requestV2,
5976
case HGFS_OP_DELETE_FILE:
5977
case HGFS_OP_DELETE_DIR: {
5978
HgfsRequestDelete *requestV1 = (HgfsRequestDelete *)payload;
5980
if (!HgfsUnpackDeletePayloadV1(requestV1,
5998
*-----------------------------------------------------------------------------
6000
* HgfsPackDeleteReply --
6002
* Pack hgfs delete reply.
6003
* Since the structure of the delete reply packet hasn't changed in
6004
* version 2 of the protocol, HgfsReplyDeleteV2 is identical to
6005
* HgfsReplyDelete. So use HgfsReplyDelete type to access packetIn to
6006
* keep the code simple.
6009
* TRUE if valid op version reply filled, FALSE otherwise.
6014
*-----------------------------------------------------------------------------
6018
HgfsPackDeleteReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
6019
char const *packetIn, // IN: incoming packet
6020
HgfsInternalStatus status, // IN: reply status
6021
HgfsOp op, // IN: requested operation
6022
char **packetOut, // OUT: outgoing packet
6023
size_t *packetSize, // OUT: size of packet
6024
HgfsSessionInfo *session) // IN: Session Info
6033
/* No reply payload, just header. */
6035
case HGFS_OP_DELETE_FILE_V3:
6036
case HGFS_OP_DELETE_DIR_V3: {
6037
HgfsReplyDeleteV3 *reply;
6039
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
6040
(void **)&reply, packetSize, session);
6043
case HGFS_OP_DELETE_FILE_V2:
6044
case HGFS_OP_DELETE_FILE:
6045
case HGFS_OP_DELETE_DIR_V2:
6046
case HGFS_OP_DELETE_DIR: {
6047
HgfsReplyDelete *reply;
6049
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
6050
(void **)&reply, packetSize, session);
6054
LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, op));
6065
*-----------------------------------------------------------------------------
6067
* HgfsUnpackRenamePayloadV3 --
6069
* Unpack hgfs rename request V3 payload and initialize a corresponding
6070
* HgfsHandles or file names to tell us old and new names/handles. Hints
6071
* holds flags to specify a handle or name for the file or
6072
* directory to rename.
6081
*-----------------------------------------------------------------------------
6085
HgfsUnpackRenamePayloadV3(HgfsRequestRenameV3 *requestV3, // IN: request payload
6086
size_t payloadSize, // IN: payload size
6087
char **cpOldName, // OUT: rename src
6088
size_t *cpOldNameLen, // OUT: rename src size
6089
char **cpNewName, // OUT: rename dst
6090
size_t *cpNewNameLen, // OUT: rename dst size
6091
HgfsRenameHint *hints, // OUT: rename hints
6092
HgfsHandle *srcFile, // OUT: src file handle
6093
HgfsHandle *targetFile, // OUT: target file handle
6094
uint32 *oldCaseFlags, // OUT: source case flags
6095
uint32 *newCaseFlags) // OUT: dest. case flags
6098
HgfsFileNameV3 *newName;
6101
LOG(4, ("%s: HGFS_OP_RENAME_V3\n", __FUNCTION__));
6103
if (payloadSize < sizeof *requestV3) {
6106
extra = payloadSize - sizeof *requestV3;
6108
*hints = requestV3->hints;
6111
* Get the old and new filenames from the request.
6113
* Getting the new filename is somewhat inconvenient, because we
6114
* don't know where request->newName actually starts, thanks to the
6115
* fact that request->oldName is of variable length. We get around
6116
* this by using an HgfsFileName*, assigning it to the correct address
6117
* just after request->oldName ends, and using that to access the
6122
* If we've been asked to reuse a handle, we don't need to look at, let
6123
* alone test the filename or its length. This applies to the source
6126
if (!HgfsUnpackFileNameV3(&requestV3->oldName,
6136
*hints |= HGFS_RENAME_HINT_USE_SRCFILE_DESC;
6137
newName = &requestV3->newName;
6139
newName = (HgfsFileNameV3 *)(requestV3->oldName.name + 1 + *cpOldNameLen);
6140
extra -= *cpOldNameLen;
6142
if (!HgfsUnpackFileNameV3(newName,
6152
*hints |= HGFS_RENAME_HINT_USE_TARGETFILE_DESC;
6160
*-----------------------------------------------------------------------------
6162
* HgfsUnpackRenamePayloadV2 --
6164
* Unpack hgfs rename request V2 payload and initialize a corresponding
6165
* HgfsHandle or file name to tell us which to delete. Hints
6166
* holds flags to specify a handle or name for the file or
6167
* directory to rename.
6176
*-----------------------------------------------------------------------------
6180
HgfsUnpackRenamePayloadV2(HgfsRequestRenameV2 *requestV2, // IN: request payload
6181
size_t payloadSize, // IN: payload size
6182
char **cpOldName, // OUT: rename src
6183
size_t *cpOldNameLen, // OUT: rename src size
6184
char **cpNewName, // OUT: rename dst
6185
size_t *cpNewNameLen, // OUT: rename dst size
6186
HgfsRenameHint *hints, // OUT: rename hints
6187
HgfsHandle *srcFile, // OUT: src file handle
6188
HgfsHandle *targetFile) // OUT: target file handle
6190
HgfsFileName *newName;
6193
/* Enforced by the dispatch function. */
6194
if (payloadSize < sizeof *requestV2) {
6197
extra = payloadSize - sizeof *requestV2;
6199
*hints = requestV2->hints;
6202
* If we've been asked to reuse a handle, we don't need to look at, let
6203
* alone test the filename or its length. This applies to the source
6207
if (*hints & HGFS_RENAME_HINT_USE_SRCFILE_DESC) {
6208
*srcFile = requestV2->srcFile;
6212
if (!HgfsUnpackFileName(&requestV2->oldName,
6218
extra -= *cpOldNameLen;
6221
if (*hints & HGFS_RENAME_HINT_USE_TARGETFILE_DESC) {
6222
*targetFile = requestV2->targetFile;
6226
newName = (HgfsFileName *)((char *)(&requestV2->oldName + 1)
6228
if (!HgfsUnpackFileName(newName,
6240
*-----------------------------------------------------------------------------
6242
* HgfsUnpackRenamePayloadV1 --
6244
* Unpack hgfs rename request V1 payload and initialize a corresponding
6245
* old and new file names.
6254
*-----------------------------------------------------------------------------
6258
HgfsUnpackRenamePayloadV1(HgfsRequestRename *requestV1, // IN: request payload
6259
size_t payloadSize, // IN: payload size
6260
char **cpOldName, // OUT: rename src
6261
size_t *cpOldNameLen, // OUT: rename src size
6262
char **cpNewName, // OUT: rename dst
6263
size_t *cpNewNameLen) // OUT: rename dst size
6265
HgfsFileName *newName;
6268
if (payloadSize < sizeof *requestV1) {
6272
extra = payloadSize - sizeof *requestV1;
6274
if (!HgfsUnpackFileName(&requestV1->oldName,
6281
extra -= requestV1->oldName.length;
6282
newName = (HgfsFileName *)((char *)(&requestV1->oldName + 1)
6283
+ requestV1->oldName.length);
6285
return HgfsUnpackFileName(newName, extra, cpNewName, cpNewNameLen);
6290
*-----------------------------------------------------------------------------
6292
* HgfsUnpackRenameRequest --
6294
* Unpack hgfs rename request and initialize a corresponding
6295
* HgfsHandle or file name to tell us which to rename. Hints
6296
* holds flags to specify a handle or name for the file or
6297
* directory to rename.
6306
*-----------------------------------------------------------------------------
6310
HgfsUnpackRenameRequest(char const *packetIn, // IN: request packet
6311
size_t packetSize, // IN: request packet size
6312
HgfsOp *op, // OUT: requested operation
6313
char **cpOldName, // OUT: rename src
6314
size_t *cpOldNameLen, // OUT: rename src size
6315
char **cpNewName, // OUT: rename dst
6316
size_t *cpNewNameLen, // OUT: rename dst size
6317
HgfsRenameHint *hints, // OUT: rename hints
6318
HgfsHandle *srcFile, // OUT: src file handle
6319
HgfsHandle *targetFile, // OUT: target file handle
6320
uint32 *oldCaseFlags, // OUT: source case-sensitivity flags
6321
uint32 *newCaseFlags) // OUT: dest. case-sensitivity flags
6323
void const *payload;
6328
ASSERT(cpOldNameLen);
6330
ASSERT(cpNewNameLen);
6334
ASSERT(oldCaseFlags);
6335
ASSERT(newCaseFlags);
6337
if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
6341
/* Default values for legacy requests. */
6342
*oldCaseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
6343
*newCaseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
6347
case HGFS_OP_RENAME_V3:
6349
HgfsRequestRenameV3 *requestV3 = (HgfsRequestRenameV3 *)payload;
6351
if (!HgfsUnpackRenamePayloadV3(requestV3,
6366
case HGFS_OP_RENAME_V2:
6368
HgfsRequestRenameV2 *requestV2 = (HgfsRequestRenameV2 *)payload;
6370
if (!HgfsUnpackRenamePayloadV2(requestV2,
6384
case HGFS_OP_RENAME:
6386
HgfsRequestRename *requestV1 = (HgfsRequestRename *)payload;
6388
if (!HgfsUnpackRenamePayloadV1(requestV1,
6408
*-----------------------------------------------------------------------------
6410
* HgfsPackRenameReply --
6412
* Pack hgfs rename reply.
6413
* Since the structure of the rename reply packet hasn't changed in
6414
* version 2 of the protocol, HgfsReplyRenameV2 is identical to
6415
* HgfsReplyRename. So use HgfsReplyRename type to access packetIn to
6416
* keep the code simple.
6419
* TRUE if valid op and reply set, FALSE otherwise.
6424
*-----------------------------------------------------------------------------
6428
HgfsPackRenameReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
6429
char const *packetIn, // IN: incoming packet
6430
HgfsInternalStatus status, // IN: reply status
6431
HgfsOp op, // IN: requested operation
6432
char **packetOut, // OUT: outgoing packet
6433
size_t *packetSize, // OUT: size of packet
6434
HgfsSessionInfo *session) // IN: Session Info
6444
case HGFS_OP_RENAME_V3: {
6445
HgfsReplyRenameV3 *reply;
6447
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
6448
(void **)&reply, packetSize, session);
6451
case HGFS_OP_RENAME_V2:
6452
case HGFS_OP_RENAME: {
6453
HgfsReplyRename *reply;
6455
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
6456
(void **)&reply, packetSize, session);
6460
LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, op));
6471
*-----------------------------------------------------------------------------
6473
* HgfsUnpackGetattrPayloadV3 --
6475
* Unpack hgfs get attr request V3 payload and initialize a corresponding
6476
* HgfsHandle or file name to tell us which file to get attributes. Hints
6477
* holds flags to specify a handle or name for the file or
6478
* directory to get attributes.
6487
*-----------------------------------------------------------------------------
6491
HgfsUnpackGetattrPayloadV3(HgfsRequestGetattrV3 *requestV3,// IN: request payload
6492
size_t payloadSize, // IN: payload size
6493
char **cpName, // OUT: cpName
6494
size_t *cpNameSize, // OUT: cpName size
6495
HgfsAttrHint *hints, // OUT: getattr hints
6496
HgfsHandle *file, // OUT: file handle
6497
uint32 *caseFlags) // OUT: case-sensitivity flags
6502
if (payloadSize < sizeof *requestV3) {
6506
*hints = requestV3->hints;
6508
result = HgfsUnpackFileNameV3(&requestV3->fileName,
6509
payloadSize - sizeof *requestV3,
6516
*hints |= HGFS_ATTR_HINT_USE_FILE_DESC;
6524
*-----------------------------------------------------------------------------
6526
* HgfsUnpackGetattrPayloadV2 --
6528
* Unpack hgfs Getattr request V2 payload and initialize a corresponding
6529
* HgfsHandle or file name to tell us which to get attributes. Hints
6530
* holds flags to specify a handle or name for the file or
6531
* directory to get attributes.
6540
*-----------------------------------------------------------------------------
6544
HgfsUnpackGetattrPayloadV2(HgfsRequestGetattrV2 *requestV2,// IN: request payload
6545
size_t payloadSize, // IN: payload size
6546
char **cpName, // OUT: cpName
6547
size_t *cpNameSize, // OUT: cpName size
6548
HgfsAttrHint *hints, // OUT: delete hints
6549
HgfsHandle *file) // OUT: file handle
6553
if (payloadSize < sizeof *requestV2) {
6558
*file = HGFS_INVALID_HANDLE;
6559
*hints = requestV2->hints;
6562
* If we've been asked to reuse a handle, we don't need to look at, let
6563
* alone test the filename or its length.
6566
if (requestV2->hints & HGFS_ATTR_HINT_USE_FILE_DESC) {
6567
*file = requestV2->file;
6571
result = HgfsUnpackFileName(&requestV2->fileName,
6572
payloadSize - sizeof *requestV2,
6581
*-----------------------------------------------------------------------------
6583
* HgfsUnpackGetattrPayloadV1 --
6585
* Unpack hgfs getattr request V1 payload and initialize a corresponding
6586
* file name to tell us which to get attributes.
6595
*-----------------------------------------------------------------------------
6599
HgfsUnpackGetattrPayloadV1(HgfsRequestGetattr *requestV1, // IN: request payload
6600
size_t payloadSize, // IN: payload size
6601
char **cpName, // OUT: cpName
6602
size_t *cpNameSize) // OUT: cpName size
6604
return HgfsUnpackFileName(&requestV1->fileName,
6605
payloadSize - sizeof *requestV1,
6612
*-----------------------------------------------------------------------------
6616
* Packs attr version 2 reply structure.
6624
*-----------------------------------------------------------------------------
6628
HgfsPackAttrV2(HgfsFileAttrInfo *attr, // IN: attr stucture
6629
HgfsAttrV2 *attr2) // OUT: attr in payload
6631
attr2->mask = attr->mask;
6632
attr2->type = attr->type;
6633
attr2->size = attr->size;
6634
attr2->creationTime = attr->creationTime;
6635
attr2->accessTime = attr->accessTime;
6636
attr2->writeTime = attr->writeTime;
6637
attr2->attrChangeTime = attr->attrChangeTime;
6638
attr2->specialPerms = attr->specialPerms;
6639
attr2->ownerPerms = attr->ownerPerms;
6640
attr2->groupPerms = attr->groupPerms;
6641
attr2->otherPerms = attr->otherPerms;
6642
attr2->flags = attr->flags;
6643
attr2->allocationSize = attr->allocationSize;
6644
attr2->userId = attr->userId;
6645
attr2->groupId = attr->groupId;
6646
attr2->hostFileId = attr->hostFileId;
6647
attr2->volumeId = attr->volumeId;
6648
attr2->effectivePerms = attr->effectivePerms;
6653
*-----------------------------------------------------------------------------
6655
* HgfsUnpackAttrV2 --
6657
* Unpacks attr version 2 reply structure.
6665
*-----------------------------------------------------------------------------
6669
HgfsUnpackAttrV2(HgfsAttrV2 *attr2, // IN: attr in payload
6670
HgfsFileAttrInfo *attr) // OUT: attr stucture
6672
attr->mask = attr2->mask;
6673
attr->type = attr2->type;
6674
attr->size = attr2->size;
6675
attr->creationTime = attr2->creationTime;
6676
attr->accessTime = attr2->accessTime;
6677
attr->writeTime = attr2->writeTime;
6678
attr->attrChangeTime = attr2->attrChangeTime;
6679
attr->specialPerms = attr2->specialPerms;
6680
attr->ownerPerms = attr2->ownerPerms;
6681
attr->groupPerms = attr2->groupPerms;
6682
attr->otherPerms = attr2->otherPerms;
6683
attr->flags = attr2->flags;
6684
attr->allocationSize = attr2->allocationSize;
6685
attr->userId = attr2->userId;
6686
attr->groupId = attr2->groupId;
6687
attr->hostFileId = attr2->hostFileId;
6688
attr->volumeId = attr2->volumeId;
6689
attr->effectivePerms = attr2->effectivePerms;
6694
*-----------------------------------------------------------------------------
6696
* HgfsInitFileAttr --
6698
* Initializes HgfsFileAttrInfo structure.
6706
*-----------------------------------------------------------------------------
6710
HgfsInitFileAttr(HgfsOp op, // IN: request type
6711
HgfsFileAttrInfo *attr) // OUT: attr stucture
6713
/* Initialize all fields with 0. */
6714
memset(attr, 0, sizeof *attr);
6716
/* Explicitly initialize fields which need it. */
6717
attr->requestType = op;
6718
attr->mask = HGFS_ATTR_VALID_NONE;
6723
*-----------------------------------------------------------------------------
6725
* HgfsPackGetattrReplyPayloadV3 --
6727
* Packs Getattr V3 reply payload.
6735
*-----------------------------------------------------------------------------
6739
HgfsPackGetattrReplyPayloadV3(HgfsFileAttrInfo *attr, // IN: attr stucture
6740
const char *utf8TargetName, // IN: optional target name
6741
uint32 utf8TargetNameLen, // IN: file name length
6742
HgfsReplyGetattrV3 *reply) // OUT: payload
6744
LOG(4, ("%s: attr type: %u\n", __FUNCTION__, reply->attr.type));
6746
HgfsPackAttrV2(attr, &reply->attr);
6747
reply->reserved = 0;
6749
if (utf8TargetName) {
6750
memcpy(reply->symlinkTarget.name, utf8TargetName, utf8TargetNameLen);
6751
CPNameLite_ConvertTo(reply->symlinkTarget.name, utf8TargetNameLen,
6754
ASSERT(utf8TargetNameLen == 0);
6756
reply->symlinkTarget.length = utf8TargetNameLen;
6757
reply->symlinkTarget.name[utf8TargetNameLen] = '\0';
6758
reply->symlinkTarget.flags = 0;
6759
reply->symlinkTarget.fid = 0;
6760
reply->symlinkTarget.caseType = HGFS_FILE_NAME_DEFAULT_CASE;
6765
*-----------------------------------------------------------------------------
6767
* HgfsPackGetattrReplyPayloadV2 --
6769
* Packs rename reply payload V2 requests.
6777
*-----------------------------------------------------------------------------
6781
HgfsPackGetattrReplyPayloadV2(HgfsHandle id, // IN: id of the request
6782
HgfsInternalStatus status, // IN: error code
6783
HgfsFileAttrInfo *attr, // IN: attr stucture
6784
const char *utf8TargetName, // IN: optional target name
6785
uint32 utf8TargetNameLen, // IN: file name length
6786
HgfsReplyGetattrV2 *reply) // OUT: payload
6788
reply->header.status = HgfsConvertFromInternalStatus(status);
6789
reply->header.id = id;
6791
HgfsPackAttrV2(attr, &reply->attr);
6793
if (utf8TargetName) {
6794
memcpy(reply->symlinkTarget.name, utf8TargetName, utf8TargetNameLen);
6795
CPNameLite_ConvertTo(reply->symlinkTarget.name, utf8TargetNameLen,
6798
ASSERT(utf8TargetNameLen == 0);
6800
reply->symlinkTarget.length = utf8TargetNameLen;
6801
reply->symlinkTarget.name[utf8TargetNameLen] = '\0';
6806
*-----------------------------------------------------------------------------
6808
* HgfsPackGetattrReplyPayloadV1 --
6810
* Packs rename reply payload for V1 requests.
6818
*-----------------------------------------------------------------------------
6822
HgfsPackGetattrReplyPayloadV1(HgfsHandle id, // IN: id of the request
6823
HgfsInternalStatus status, // IN: error code
6824
HgfsFileAttrInfo *attr, // IN: attr stucture
6825
HgfsReplyGetattr *reply) // OUT: reply info
6827
reply->header.status = HgfsConvertFromInternalStatus(status);
6828
reply->header.id = id;
6830
/* In GetattrV1, symlinks are treated as regular files. */
6831
if (attr->type == HGFS_FILE_TYPE_SYMLINK) {
6832
reply->attr.type = HGFS_FILE_TYPE_REGULAR;
6834
reply->attr.type = attr->type;
6837
reply->attr.size = attr->size;
6838
reply->attr.creationTime = attr->creationTime;
6839
reply->attr.accessTime = attr->accessTime;
6840
reply->attr.writeTime = attr->writeTime;
6841
reply->attr.attrChangeTime = attr->attrChangeTime;
6842
reply->attr.permissions = attr->ownerPerms;
6847
*-----------------------------------------------------------------------------
6849
* HgfsValidateReplySize --
6851
* Verify if the size of a reply does not exceed maximum supported size.
6854
* TRUE if the packet size is acceptable, FALSE otherwise.
6859
*-----------------------------------------------------------------------------
6863
HgfsValidateReplySize(char const *packetIn,
6867
HgfsRequest *request = (HgfsRequest *)packetIn;
6870
* At the moment assume that V4 protocol does not impose any restrictions
6871
* on the packet size.
6872
* May need to review later.
6874
if (HGFS_V4_LEGACY_OPCODE == request->op) {
6878
if (HGFS_OP_READ_V3 == op) {
6879
return packetSize <= HGFS_LARGE_PACKET_MAX;
6882
return packetSize <= HGFS_PACKET_MAX;
6887
*-----------------------------------------------------------------------------
6889
* HgfsUnpackGetattrRequest --
6891
* Unpack hgfs getattr request and initialize a corresponding
6892
* HgfsFileAttrInfo structure that is used to pass around getattr request
6895
* Since the structure of the get attributes request packet hasn't changed
6896
* in version 2 of the protocol, HgfsRequestGetattrV2 is identical to
6897
* HgfsRequestGetattr. So use HgfsRequestGetattr type to access packetIn to
6898
* keep the code simple.
6907
*-----------------------------------------------------------------------------
6911
HgfsUnpackGetattrRequest(char const *packetIn, // IN: request packet
6912
size_t packetSize, // IN: request packet size
6913
HgfsFileAttrInfo *attrInfo, // IN/OUT: getattr info
6914
HgfsAttrHint *hints, // OUT: getattr hints
6915
char **cpName, // OUT: cpName
6916
size_t *cpNameSize, // OUT: cpName size
6917
HgfsHandle *file, // OUT: file handle
6918
uint32 *caseType) // OUT: case-sensitivity flags
6920
void const *payload;
6931
if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, &op)) {
6935
HgfsInitFileAttr(op, attrInfo);
6937
/* Default values for legacy requests. */
6938
*caseType = HGFS_FILE_NAME_DEFAULT_CASE;
6940
*file = HGFS_INVALID_HANDLE;
6943
case HGFS_OP_GETATTR_V3: {
6944
HgfsRequestGetattrV3 *requestV3 = (HgfsRequestGetattrV3 *)payload;
6946
if (!HgfsUnpackGetattrPayloadV3(requestV3,
6955
LOG(4, ("%s: HGFS_OP_GETATTR_V3: %u\n", __FUNCTION__, *caseType));
6959
case HGFS_OP_GETATTR_V2: {
6960
HgfsRequestGetattrV2 *requestV2 = (HgfsRequestGetattrV2 *)payload;
6962
if (!HgfsUnpackGetattrPayloadV2(requestV2,
6973
case HGFS_OP_GETATTR: {
6974
HgfsRequestGetattr *requestV1 = (HgfsRequestGetattr *)payload;
6976
if (!HgfsUnpackGetattrPayloadV1(requestV1,payloadSize, cpName, cpNameSize)) {
6991
*-----------------------------------------------------------------------------
6993
* HgfsPackGetattrReply --
6995
* Pack hgfs getattr reply to the HgfsReplyGetattr structure.
7004
*-----------------------------------------------------------------------------
7008
HgfsPackGetattrReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
7009
char const *packetIn, // IN: incoming packet
7010
HgfsInternalStatus status, // IN: reply status
7011
HgfsFileAttrInfo *attr, // IN: attr stucture
7012
const char *utf8TargetName, // IN: optional target name
7013
uint32 utf8TargetNameLen, // IN: file name length
7014
char **packetOut, // OUT: outgoing packet
7015
size_t *packetSize, // OUT: size of packet
7016
HgfsSessionInfo *session) // IN: Session Info
7025
switch (attr->requestType) {
7026
case HGFS_OP_GETATTR_V3: {
7027
HgfsReplyGetattrV3 *reply;
7028
uint32 payloadSize = sizeof *reply + utf8TargetNameLen;
7030
result = HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7031
(void **)&reply, packetSize, session);
7032
if (result == FALSE) {
7036
if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7040
HgfsPackGetattrReplyPayloadV3(attr, utf8TargetName, utf8TargetNameLen, reply);
7044
case HGFS_OP_GETATTR_V2: {
7045
HgfsReplyGetattrV2 *reply;
7046
HgfsRequest *request = (HgfsRequest *)packetIn;
7047
uint32 payloadSize = sizeof *reply + utf8TargetNameLen;
7049
result = HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7050
(void **)&reply, packetSize, session);
7051
if (result == FALSE) {
7055
if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7059
HgfsPackGetattrReplyPayloadV2(request->id,
7068
case HGFS_OP_GETATTR: {
7069
HgfsReplyGetattr *reply;
7070
HgfsRequest *request = (HgfsRequest *)packetIn;
7072
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
7073
(void **)&reply, packetSize, session);
7074
if (result == FALSE) {
7078
HgfsPackGetattrReplyPayloadV1(request->id, status, attr, reply);
7083
LOG(4, ("%s: Invalid GetAttr op.\n", __FUNCTION__));
7094
*-----------------------------------------------------------------------------
7096
* HgfsPackSearchReadReplyPayloadV3 --
7098
* Packs SearchRead V3 reply payload.
7106
*-----------------------------------------------------------------------------
7110
HgfsPackSearchReadReplyPayloadV3(HgfsFileAttrInfo *attr, // IN: attr stucture
7111
const char *utf8Name, // IN: file name
7112
uint32 utf8NameLen, // IN: file name length
7113
HgfsReplySearchReadV3 *reply) // OUT: payload
7115
HgfsDirEntry *dirent = (HgfsDirEntry *)reply->payload;
7118
reply->reserved = 0;
7120
dirent->fileName.length = (uint32)utf8NameLen;
7121
dirent->fileName.flags = 0;
7122
dirent->fileName.fid = 0;
7123
dirent->fileName.caseType = HGFS_FILE_NAME_DEFAULT_CASE;
7124
dirent->nextEntry = 0;
7126
if (utf8NameLen != 0) {
7127
memcpy(dirent->fileName.name, utf8Name, utf8NameLen);
7128
dirent->fileName.name[utf8NameLen] = 0;
7130
HgfsPackAttrV2(attr, &dirent->attr);
7136
*-----------------------------------------------------------------------------
7138
* HgfsPackSearchReadReplyPayloadV2 --
7140
* Packs SearchRead V2 reply payload.
7148
*-----------------------------------------------------------------------------
7152
HgfsPackSearchReadReplyPayloadV2(HgfsFileAttrInfo *attr, // IN: attr stucture
7153
const char *utf8Name, // IN: file name
7154
uint32 utf8NameLen, // IN: file name length
7155
HgfsReplySearchReadV2 *reply) // OUT: payload
7157
reply->fileName.length = (uint32)utf8NameLen;
7159
if (utf8NameLen != 0) {
7160
memcpy(reply->fileName.name, utf8Name, utf8NameLen);
7161
reply->fileName.name[utf8NameLen] = 0;
7162
HgfsPackAttrV2(attr, &reply->attr);
7168
*-----------------------------------------------------------------------------
7170
* HgfsPackSearchReadReplyPayloadV1 --
7172
* Packs SearchRead V1 reply payload.
7180
*-----------------------------------------------------------------------------
7184
HgfsPackSearchReadReplyPayloadV1(HgfsFileAttrInfo *attr, // IN: attr stucture
7185
const char *utf8Name, // IN: file name
7186
uint32 utf8NameLen, // IN: file name length
7187
HgfsReplySearchRead *reply) // OUT: payload
7189
reply->fileName.length = (uint32)utf8NameLen;
7191
if (utf8NameLen != 0) {
7192
memcpy(reply->fileName.name, utf8Name, utf8NameLen);
7193
reply->fileName.name[utf8NameLen] = 0;
7195
/* In SearchReadV1, symlinks are treated as regular files. */
7196
if (attr->type == HGFS_FILE_TYPE_SYMLINK) {
7197
reply->attr.type = HGFS_FILE_TYPE_REGULAR;
7199
reply->attr.type = attr->type;
7201
reply->attr.size = attr->size;
7202
reply->attr.creationTime = attr->creationTime;
7203
reply->attr.accessTime = attr->accessTime;
7204
reply->attr.writeTime = attr->writeTime;
7205
reply->attr.attrChangeTime = attr->attrChangeTime;
7206
reply->attr.permissions = attr->ownerPerms;
7212
*-----------------------------------------------------------------------------
7214
* HgfsUnpackSearchReadRequest --
7216
* Unpack hgfs search read request and initialize a corresponding
7217
* HgfsFileAttrInfo structure that is used to pass around attribute
7220
* Since the structure of the search read request packet hasn't changed in
7221
* version 2 of the protocol, HgfsRequestSearchReadV2 is identical to
7222
* HgfsRequestSearchRead. So use HgfsRequestSearchRead type to access
7223
* packetIn to keep the code simple.
7231
*-----------------------------------------------------------------------------
7235
HgfsUnpackSearchReadRequest(const char *packetIn, // IN: request packet
7236
size_t packetSize, // IN: packet size
7237
HgfsFileAttrInfo *attr, // OUT: unpacked attr struct
7238
HgfsHandle *hgfsSearchHandle, // OUT: hgfs search handle
7239
uint32 *offset) // OUT: entry offset
7241
void const *payload;
7247
ASSERT(hgfsSearchHandle);
7250
if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, &op)) {
7254
HgfsInitFileAttr(op, attr);
7257
if (op == HGFS_OP_SEARCH_READ_V3) {
7258
HgfsRequestSearchReadV3 *request = (HgfsRequestSearchReadV3 *)payload;
7260
/* Enforced by the dispatch function. */
7261
ASSERT(payloadSize >= sizeof *request);
7263
*hgfsSearchHandle = request->search;
7264
*offset = request->offset;
7266
LOG(4, ("%s: HGFS_OP_SEARCH_READ_V3\n", __FUNCTION__));
7268
HgfsRequestSearchRead *request = (HgfsRequestSearchRead *)payload;
7270
/* Enforced by the dispatch function. */
7271
ASSERT(payloadSize >= sizeof *request);
7273
*hgfsSearchHandle = request->search;
7274
*offset = request->offset;
7282
*-----------------------------------------------------------------------------
7284
* HgfsPackSearchReadReply --
7286
* Pack hgfs search read reply to the HgfsReplySearchRead{V2} structure.
7295
*-----------------------------------------------------------------------------
7299
HgfsPackSearchReadReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
7300
char const *packetIn, // IN: incoming packet
7301
HgfsInternalStatus status, // IN: reply status
7302
const char *utf8Name, // IN: file name
7303
size_t utf8NameLen, // IN: file name length
7304
HgfsFileAttrInfo *attr, // IN: file attr struct
7305
char **packetOut, // OUT: outgoing packet
7306
size_t *packetSize, // OUT: size of packet
7307
HgfsSessionInfo *session) // IN: Session Info
7315
switch (attr->requestType) {
7316
case HGFS_OP_SEARCH_READ_V3: {
7317
HgfsReplySearchReadV3 *reply;
7318
uint32 payloadSize = sizeof *reply + utf8NameLen + sizeof(HgfsDirEntry);
7320
if (!HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7321
(void **)&reply, packetSize, session)) {
7326
if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7331
HgfsPackSearchReadReplyPayloadV3(attr, utf8Name, utf8NameLen, reply);
7335
case HGFS_OP_SEARCH_READ_V2: {
7336
HgfsReplySearchReadV2 *reply;
7337
uint32 payloadSize = sizeof *reply + utf8NameLen;
7339
if (!HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7340
(void **)&reply, packetSize, session)) {
7345
if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7350
HgfsPackSearchReadReplyPayloadV2(attr,
7357
case HGFS_OP_SEARCH_READ: {
7358
HgfsReplySearchRead *reply;
7359
uint32 payloadSize = sizeof *reply + utf8NameLen;
7361
if (!HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7362
(void **)&reply, packetSize, session)) {
7367
if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7372
HgfsPackSearchReadReplyPayloadV1(attr,
7380
LOG(4, ("%s: Invalid SearchRead Op.", __FUNCTION__));
7392
*-----------------------------------------------------------------------------
7394
* HgfsUnpackSetattrPayloadV3 --
7396
* Unpack hgfs set attr request V3 payload and initialize a corresponding
7397
* HgfsHandle or file name to tell us which file to set attributes. Hints
7398
* holds flags to specify a handle or name for the file or
7399
* directory to set attributes.
7408
*-----------------------------------------------------------------------------
7412
HgfsUnpackSetattrPayloadV3(HgfsRequestSetattrV3 *requestV3,// IN: request payload
7413
size_t payloadSize, // IN: payload size
7414
HgfsFileAttrInfo *attr, // OUT: setattr info
7415
char **cpName, // OUT: cpName
7416
size_t *cpNameSize, // OUT: cpName size
7417
HgfsAttrHint *hints, // OUT: getattr hints
7418
HgfsHandle *file, // OUT: file handle
7419
uint32 *caseFlags) // OUT: case-sensitivity flags
7424
if (payloadSize < sizeof *requestV3) {
7428
*hints = requestV3->hints;
7430
HgfsUnpackAttrV2(&requestV3->attr, attr);
7432
result = HgfsUnpackFileNameV3(&requestV3->fileName,
7433
payloadSize - sizeof *requestV3,
7440
*hints |= HGFS_ATTR_HINT_USE_FILE_DESC;
7443
LOG(4, ("%s: unpacking HGFS_OP_SETATTR_V3, %u\n", __FUNCTION__,
7450
*-----------------------------------------------------------------------------
7452
* HgfsUnpackSetattrPayloadV2 --
7454
* Unpack hgfs Setattr request V2 payload and initialize a corresponding
7455
* HgfsHandle or file name to tell us which to set attributes. Hints
7456
* holds flags to specify a handle or name for the file or
7457
* directory to set attributes.
7466
*-----------------------------------------------------------------------------
7470
HgfsUnpackSetattrPayloadV2(HgfsRequestSetattrV2 *requestV2,// IN: request payload
7471
size_t payloadSize, // IN: payload size
7472
HgfsFileAttrInfo *attr, // OUT: setattr info
7473
char **cpName, // OUT: cpName
7474
size_t *cpNameSize, // OUT: cpName size
7475
HgfsAttrHint *hints, // OUT: delete hints
7476
HgfsHandle *file) // OUT: file handle
7480
/* Enforced by the dispatch function. */
7481
if (payloadSize < sizeof *requestV2) {
7485
LOG(4, ("%s: unpacking HGFS_OP_SETATTR_V2\n", __FUNCTION__));
7487
*file = HGFS_INVALID_HANDLE;
7488
*hints = requestV2->hints;
7490
HgfsUnpackAttrV2(&requestV2->attr, attr);
7492
if (requestV2->hints & HGFS_ATTR_HINT_USE_FILE_DESC) {
7493
*file = requestV2->file;
7497
result = HgfsUnpackFileName(&requestV2->fileName,
7498
payloadSize - sizeof *requestV2,
7507
*-----------------------------------------------------------------------------
7509
* HgfsUnpackSetattrPayloadV1 --
7511
* Unpack hgfs setattr request V1 payload and initialize a corresponding
7512
* file name to tell us which to set attributes.
7521
*-----------------------------------------------------------------------------
7525
HgfsUnpackSetattrPayloadV1(HgfsRequestSetattr *requestV1, // IN: request payload
7526
size_t payloadSize, // IN: payload size
7527
HgfsFileAttrInfo *attr, // OUT: setattr info
7528
char **cpName, // OUT: cpName
7529
size_t *cpNameSize, // OUT: cpName size
7530
HgfsAttrHint *hints) // OUT: setattr hints
7532
LOG(4, ("%s: unpacking HGFS_OP_SETATTR\n", __FUNCTION__));
7535
attr->mask |= requestV1->update & HGFS_ATTR_SIZE ? HGFS_ATTR_VALID_SIZE : 0;
7536
attr->mask |= requestV1->update & HGFS_ATTR_CREATE_TIME ?
7537
HGFS_ATTR_VALID_CREATE_TIME : 0;
7538
attr->mask |= requestV1->update & HGFS_ATTR_ACCESS_TIME ?
7539
HGFS_ATTR_VALID_ACCESS_TIME : 0;
7540
attr->mask |= requestV1->update & HGFS_ATTR_WRITE_TIME ?
7541
HGFS_ATTR_VALID_WRITE_TIME : 0;
7542
attr->mask |= requestV1->update & HGFS_ATTR_CHANGE_TIME ?
7543
HGFS_ATTR_VALID_CHANGE_TIME : 0;
7544
attr->mask |= requestV1->update & HGFS_ATTR_PERMISSIONS ?
7545
HGFS_ATTR_VALID_OWNER_PERMS : 0;
7546
*hints |= requestV1->update & HGFS_ATTR_ACCESS_TIME_SET ?
7547
HGFS_ATTR_HINT_SET_ACCESS_TIME : 0;
7548
*hints |= requestV1->update & HGFS_ATTR_WRITE_TIME_SET ?
7549
HGFS_ATTR_HINT_SET_WRITE_TIME : 0;
7551
attr->type = requestV1->attr.type;
7552
attr->size = requestV1->attr.size;
7553
attr->creationTime = requestV1->attr.creationTime;
7554
attr->accessTime = requestV1->attr.accessTime;
7555
attr->writeTime = requestV1->attr.writeTime;
7556
attr->attrChangeTime = requestV1->attr.attrChangeTime;
7557
attr->ownerPerms = requestV1->attr.permissions;
7558
return HgfsUnpackFileName(&requestV1->fileName,
7559
payloadSize - sizeof *requestV1,
7566
*-----------------------------------------------------------------------------
7568
* HgfsUnpackSetattrRequest --
7570
* Unpack hgfs setattr request and initialize a corresponding
7571
* HgfsFileAttrInfo structure that is used to pass around setattr request
7581
*-----------------------------------------------------------------------------
7585
HgfsUnpackSetattrRequest(char const *packetIn, // IN: request packet
7586
size_t packetSize, // IN: request packet size
7587
HgfsFileAttrInfo *attr, // OUT: setattr info
7588
HgfsAttrHint *hints, // OUT: setattr hints
7589
char **cpName, // OUT: cpName
7590
size_t *cpNameSize, // OUT: cpName size
7591
HgfsHandle *file, // OUT: server file ID
7592
uint32 *caseType) // OUT: case-sensitivity flags
7594
void const *payload;
7605
if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, &op)) {
7609
attr->requestType = op;
7611
/* Default values for legacy requests. */
7612
*caseType = HGFS_FILE_NAME_DEFAULT_CASE;
7614
*file = HGFS_INVALID_HANDLE;
7617
case HGFS_OP_SETATTR_V3:
7619
HgfsRequestSetattrV3 *requestV3 = (HgfsRequestSetattrV3 *)payload;
7620
if (!HgfsUnpackSetattrPayloadV3(requestV3,
7633
case HGFS_OP_SETATTR_V2:
7635
HgfsRequestSetattrV2 *requestV2 = (HgfsRequestSetattrV2 *)payload;
7636
if (!HgfsUnpackSetattrPayloadV2(requestV2,
7647
case HGFS_OP_SETATTR:
7649
HgfsRequestSetattr *requestV1 = (HgfsRequestSetattr *)payload;
7650
if (!HgfsUnpackSetattrPayloadV1(requestV1,
7669
*-----------------------------------------------------------------------------
7671
* HgfsPackSetattrReply --
7673
* Pack hgfs setattr reply.
7674
* Since the structure of the set attributes reply packet hasn't changed in
7675
* version 2 of the protocol, HgfsReplySetattrV2 is identical to
7676
* HgfsReplySetattr. So use HgfsReplySetattr type to access packetIn to
7677
* keep the code simple.
7680
* TRUE if valid op and reply set, FALSE otherwise.
7685
*-----------------------------------------------------------------------------
7689
HgfsPackSetattrReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
7690
char const *packetIn, // IN: incoming packet
7691
HgfsInternalStatus status, // IN: reply status
7692
HgfsOp op, // IN: request type
7693
char **packetOut, // OUT: outgoing packet
7694
size_t *packetSize, // OUT: size of packet
7695
HgfsSessionInfo *session) // IN: Session Info
7705
case HGFS_OP_SETATTR_V3: {
7706
HgfsReplySetattrV3 *reply;
7708
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
7709
(void **)&reply, packetSize, session);
7712
case HGFS_OP_SETATTR_V2:
7713
case HGFS_OP_SETATTR: {
7714
HgfsReplySetattr *reply;
7716
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
7717
(void **)&reply, packetSize, session);
7722
LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, op));
7734
*-----------------------------------------------------------------------------
7736
* HgfsUnpackCreateDirPayloadV3 --
7738
* Unpack hgfs create directory request V3 payload and initialize a corresponding
7739
* file name to tell us which directory to create.
7748
*-----------------------------------------------------------------------------
7752
HgfsUnpackCreateDirPayloadV3(HgfsRequestCreateDirV3 *requestV3, // IN: request payload
7753
size_t payloadSize, // IN: payload size
7754
HgfsCreateDirInfo *info) // IN/OUT: info struct
7757
* The request file name length is user-provided, so this test must be
7758
* carefully written to prevent wraparounds.
7761
LOG(4, ("%s: HGFS_OP_CREATE_DIR_V3\n", __FUNCTION__));
7762
ASSERT(payloadSize >= sizeof *requestV3);
7763
if (requestV3->fileName.length > payloadSize - sizeof *requestV3) {
7764
/* The input packet is smaller than the request. */
7767
if (!(requestV3->mask & HGFS_CREATE_DIR_VALID_FILE_NAME)) {
7768
/* We do not support requests without a valid file name. */
7773
* Copy all the fields into our carrier struct. Some will probably be
7774
* garbage, but it's simpler to copy everything now and check the
7775
* valid bits before reading later.
7778
info->mask = requestV3->mask;
7779
info->cpName = requestV3->fileName.name;
7780
info->cpNameSize = requestV3->fileName.length;
7781
info->caseFlags = requestV3->fileName.caseType;
7782
info->specialPerms = requestV3->specialPerms;
7783
info->fileAttr = requestV3->fileAttr;
7784
info->ownerPerms = requestV3->ownerPerms;
7785
info->groupPerms = requestV3->groupPerms;
7786
info->otherPerms = requestV3->otherPerms;
7792
*-----------------------------------------------------------------------------
7794
* HgfsUnpackCreateDirPayloadV2 --
7796
* Unpack hgfs create directory request V2 payload and initialize a corresponding
7797
* file name to tell us which directory to create.
7806
*-----------------------------------------------------------------------------
7810
HgfsUnpackCreateDirPayloadV2(HgfsRequestCreateDirV2 *requestV2, // IN: request payload
7811
size_t payloadSize, // IN: payload size
7812
HgfsCreateDirInfo *info) // IN/OUT: info struct
7815
* The request file name length is user-provided, so this test must be
7816
* carefully written to prevent wraparounds.
7819
LOG(4, ("%s: HGFS_OP_CREATE_DIR_V2\n", __FUNCTION__));
7820
ASSERT(payloadSize >= sizeof *requestV2);
7821
if (requestV2->fileName.length > payloadSize - sizeof *requestV2) {
7822
/* The input packet is smaller than the request. */
7825
if (!(requestV2->mask & HGFS_CREATE_DIR_VALID_FILE_NAME)) {
7826
/* We do not support requests without a valid file name. */
7831
* Copy all the fields into our carrier struct. Some will probably be
7832
* garbage, but it's simpler to copy everything now and check the
7833
* valid bits before reading later.
7836
info->mask = requestV2->mask;
7837
info->cpName = requestV2->fileName.name;
7838
info->cpNameSize = requestV2->fileName.length;
7839
info->specialPerms = requestV2->specialPerms;
7840
info->ownerPerms = requestV2->ownerPerms;
7841
info->groupPerms = requestV2->groupPerms;
7842
info->otherPerms = requestV2->otherPerms;
7849
*-----------------------------------------------------------------------------
7851
* HgfsUnpackCreateDirPayloadV1 --
7853
* Unpack hgfs create directory request V1 payload and initialize a corresponding
7854
* file name to tell us which directory to create.
7863
*-----------------------------------------------------------------------------
7867
HgfsUnpackCreateDirPayloadV1(HgfsRequestCreateDir *requestV1, // IN: request payload
7868
size_t payloadSize, // IN: payload size
7869
HgfsCreateDirInfo *info) // IN/OUT: info struct
7872
* The request file name length is user-provided, so this test must be
7873
* carefully written to prevent wraparounds.
7876
LOG(4, ("%s: HGFS_OP_CREATE_DIR_V1\n", __FUNCTION__));
7877
ASSERT(payloadSize >= sizeof *requestV1);
7878
if (requestV1->fileName.length > payloadSize - sizeof *requestV1) {
7879
/* The input packet is smaller than the request. */
7883
/* For CreateDirV1 requests, we know exactly what fields we expect. */
7884
info->mask = HGFS_CREATE_DIR_VALID_OWNER_PERMS | HGFS_CREATE_DIR_VALID_FILE_NAME;
7885
info->cpName = requestV1->fileName.name;
7886
info->cpNameSize = requestV1->fileName.length;
7887
info->ownerPerms = requestV1->permissions;
7894
*-----------------------------------------------------------------------------
7896
* HgfsUnpackCreateDirRequest --
7898
* Unpack hgfs CreateDir request and initialize a corresponding
7899
* HgfsCreateDirInfo structure that is used to pass around CreateDir request
7909
*-----------------------------------------------------------------------------
7913
HgfsUnpackCreateDirRequest(char const *packetIn, // IN: incoming packet
7914
size_t packetSize, // IN: size of packet
7915
HgfsCreateDirInfo *info) // IN/OUT: info struct
7917
void const *payload;
7924
if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, &op)) {
7928
info->requestType = op;
7929
/* Default value for legacy requests. */
7930
info->caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
7933
case HGFS_OP_CREATE_DIR_V3:
7935
HgfsRequestCreateDirV3 *requestV3 = (HgfsRequestCreateDirV3 *)payload;
7936
if (!HgfsUnpackCreateDirPayloadV3(requestV3,
7944
case HGFS_OP_CREATE_DIR_V2:
7946
HgfsRequestCreateDirV2 *requestV2 = (HgfsRequestCreateDirV2 *)payload;
7947
if (!HgfsUnpackCreateDirPayloadV2(requestV2,
7954
case HGFS_OP_CREATE_DIR:
7956
HgfsRequestCreateDir *requestV1 = (HgfsRequestCreateDir *)payload;
7957
if (!HgfsUnpackCreateDirPayloadV1(requestV1,
7973
*-----------------------------------------------------------------------------
7975
* HgfsPackCreateDirReply --
7977
* Pack hgfs CreateDir reply.
7980
* TRUE if valid op and reply set, FALSE otherwise.
7985
*-----------------------------------------------------------------------------
7989
HgfsPackCreateDirReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
7990
char const *packetIn, // IN: create dir operation version
7991
HgfsInternalStatus status, // IN: reply status
7992
HgfsOp op, // IN: request type
7993
char **packetOut, // OUT: outgoing packet
7994
size_t *packetSize, // OUT: size of packet
7995
HgfsSessionInfo *session) // IN: Session Info
8005
case HGFS_OP_CREATE_DIR_V3: {
8006
HgfsReplyCreateDirV3 *reply;
8008
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
8009
(void **)&reply, packetSize, session);
8012
case HGFS_OP_CREATE_DIR_V2: {
8013
HgfsReplyCreateDirV2 *reply;
8015
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
8016
(void **)&reply, packetSize, session);
8019
case HGFS_OP_CREATE_DIR: {
8020
HgfsReplyCreateDir *reply;
8022
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
8023
(void **)&reply, packetSize, session);
8028
LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, op));
8038
*-----------------------------------------------------------------------------
8040
* HgfsUnpackWriteWin32StreamPayloadV3 --
8042
* Unpack hgfs write stream request V3 payload and initialize a corresponding
8043
* file name to tell us which directory to create.
8052
*-----------------------------------------------------------------------------
8056
HgfsUnpackWriteWin32StreamPayloadV3(HgfsRequestWriteWin32StreamV3 *requestV3, // IN:
8057
size_t payloadSize, // IN:
8058
HgfsHandle *file, // OUT:
8059
char **data, // OUT:
8060
size_t *dataSize, // OUT:
8061
Bool *doSecurity) // OUT:
8063
LOG(4, ("%s: HGFS_OP_WRITE_WIN32_STREAM_V3\n", __FUNCTION__));
8064
if (payloadSize < sizeof *requestV3) {
8068
if (payloadSize >= requestV3->requiredSize + sizeof *requestV3) {
8069
*file = requestV3->file;
8070
*data = requestV3->payload;
8071
*dataSize = requestV3->requiredSize;
8072
*doSecurity = (requestV3->flags & HGFS_WIN32_STREAM_IGNORE_SECURITY) == 0;
8080
*-----------------------------------------------------------------------------
8082
* HgfsUnpackWriteWin32StreamRequest --
8084
* Unpack hgfs SendFileUsingReader request. Returns file to write to, data
8085
* and whether to restore the security stream.
8094
*-----------------------------------------------------------------------------
8098
HgfsUnpackWriteWin32StreamRequest(char const *packetIn, // IN: incoming packet
8099
size_t packetSize, // IN: size of packet
8100
HgfsOp *op, // OUT: request type
8101
HgfsHandle *file, // OUT: file to write to
8102
char **data, // OUT: data to write
8103
size_t *dataSize, // OUT: size of data
8104
Bool *doSecurity) // OUT: restore sec.str.
8106
void const *payload;
8115
if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
8119
if (*op != HGFS_OP_WRITE_WIN32_STREAM_V3) {
8120
/* The only supported version for the moment is V3. */
8125
return HgfsUnpackWriteWin32StreamPayloadV3((HgfsRequestWriteWin32StreamV3 *)payload,
8135
*-----------------------------------------------------------------------------
8137
* HgfsPackWriteWin32StreamReply --
8139
* Pack hgfs SendFileUsingReader reply.
8140
* Returns the actual amount of data written in the reply.
8143
* TRUE if valid op and reply set, FALSE otherwise.
8148
*-----------------------------------------------------------------------------
8152
HgfsPackWriteWin32StreamReply(HgfsPacket *packet, // IN/OUT: Hgfs Packet
8153
char const *packetIn, // IN: incoming packet
8154
HgfsInternalStatus status, // IN: reply status
8155
HgfsOp op, // IN: request type
8156
uint32 actualSize, // IN: amount written
8157
char **packetOut, // OUT: outgoing packet
8158
size_t *packetSize, // OUT: size of packet
8159
HgfsSessionInfo *session) // IN:Session Info
8161
HgfsReplyWriteWin32StreamV3 *reply;
8169
if (op != HGFS_OP_WRITE_WIN32_STREAM_V3) {
8174
result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
8175
(void **)&reply, packetSize, session);
8176
if (result != FALSE) {
8177
reply->actualSize = actualSize;
4673
replyPacketSize = headerSize + payloadSize;
4674
reply = HSPU_GetReplyPacket(packet, &replyPacketSize, session);
4676
if (reply && (replyPacketSize >= headerSize + payloadSize)) {
4678
if (payloadSize > 0) {
4679
*payload = reply + headerSize;
4690
*-----------------------------------------------------------------------------
4694
* Handle a Read request.
4697
* HGFS_ERROR_SUCCESS on success.
4698
* HGFS error code on failure.
4703
*-----------------------------------------------------------------------------
4707
HgfsServerRead(HgfsInputParam *input) // IN: Input params
4709
HgfsInternalStatus status;
4712
uint32 requiredSize;
4713
size_t replyPayloadSize = 0;
4715
HGFS_ASSERT_INPUT(input);
4717
if (!HgfsUnpackReadRequest(input->payload, input->payloadSize, input->op, &file,
4718
&offset, &requiredSize)) {
4719
status = HGFS_ERROR_PROTOCOL;
4722
case HGFS_OP_READ_FAST_V4:
4723
case HGFS_OP_READ_V3: {
4724
HgfsReplyReadV3 *reply;
4726
uint32 inlineDataSize =
4727
(HGFS_OP_READ_FAST_V4 == input->op) ? 0 : requiredSize;
4729
if (!HgfsAllocInitReply(input->packet, input->metaPacket,
4730
sizeof *reply + inlineDataSize, (void **)&reply,
4732
status = HGFS_ERROR_PROTOCOL;
4734
if (inlineDataSize > 0) {
4735
payload = reply->payload;
4737
payload = HSPU_GetDataPacketBuf(input->packet, BUF_WRITEABLE,
4741
status = HgfsPlatformReadFile(file, input->session, offset,
4742
requiredSize, payload,
4743
&reply->actualSize);
4744
if (HGFS_ERROR_SUCCESS == status) {
4745
replyPayloadSize = sizeof *reply +
4746
((inlineDataSize > 0) ? reply->actualSize : 0);
4749
status = HGFS_ERROR_PROTOCOL;
4754
case HGFS_OP_READ: {
4755
HgfsReplyRead *reply;
4757
if (HgfsAllocInitReply(input->packet, input->metaPacket,
4758
sizeof *reply + requiredSize, (void **)&reply,
4760
status = HgfsPlatformReadFile(file, input->session, offset, requiredSize,
4761
reply->payload, &reply->actualSize);
4762
if (HGFS_ERROR_SUCCESS == status) {
4763
replyPayloadSize = sizeof *reply + reply->actualSize;
4766
status = HGFS_ERROR_PROTOCOL;
4772
status = HGFS_ERROR_PROTOCOL;
4776
HgfsServerCompleteRequest(status, replyPayloadSize, input);
4781
*-----------------------------------------------------------------------------
4783
* HgfsServerWrite --
4785
* Handle a Write request.
4793
*-----------------------------------------------------------------------------
4797
HgfsServerWrite(HgfsInputParam *input) // IN: Input params
4799
uint32 numberBytesToWrite;
4800
HgfsInternalStatus status;
4801
HgfsWriteFlags flags;
4804
uint32 replyActualSize;
4805
size_t replyPayloadSize = 0;
4808
HGFS_ASSERT_INPUT(input);
4810
if (HgfsUnpackWriteRequest(input, &file, &offset, &numberBytesToWrite,
4811
&flags, &dataToWrite)) {
4813
status = HgfsPlatformWriteFile(file, input->session, offset, numberBytesToWrite,
4814
flags, dataToWrite, &replyActualSize);
4815
if (HGFS_ERROR_SUCCESS == status) {
4816
if (!HgfsPackWriteReply(input->packet, input->metaPacket, input->op,
4817
replyActualSize, &replyPayloadSize, input->session)) {
4818
status = HGFS_ERROR_INTERNAL;
4822
status = HGFS_ERROR_PROTOCOL;
4825
HgfsServerCompleteRequest(status, replyPayloadSize, input);
4830
*-----------------------------------------------------------------------------
4832
* HgfsQueryVolume --
4834
* Performs actual work to get free space and capacity for a volume or
4835
* a group of volumes.
4839
* Non-zero on failure.
4845
*-----------------------------------------------------------------------------
4848
HgfsQueryVolume(HgfsSessionInfo *session, // IN: session info
4849
char *fileName, // IN: cpName for the volume
4850
size_t fileNameLength, // IN: cpName length
4851
uint32 caseFlags, // IN: case sensitive/insensitive name
4852
uint64 *freeBytes, // OUT: free space in bytes
4853
uint64 *totalBytes) // OUT: capacity in bytes
4855
HgfsInternalStatus status = HGFS_ERROR_SUCCESS;
4856
uint64 outFreeBytes;
4857
uint64 outTotalBytes;
4858
char *utf8Name = NULL;
4860
HgfsNameStatus nameStatus;
4861
Bool firstShare = TRUE;
4862
HgfsShareInfo shareInfo;
4864
VolumeInfoType infoType;
4865
DirectoryEntry *dent;
4869
HgfsInternalStatus firstErr = HGFS_ERROR_SUCCESS;
4872
/* It is now safe to read the file name field. */
4873
nameStatus = HgfsServerGetShareInfo(fileName,
4880
switch (nameStatus) {
4881
case HGFS_NAME_STATUS_INCOMPLETE_BASE:
4883
* This is the base of our namespace. Clients can request a
4884
* QueryVolumeInfo on it, on individual shares, or on just about
4888
LOG(4,("%s: opened search on base\n", __FUNCTION__));
4889
status = HgfsServerSearchVirtualDir(HgfsServerPolicy_GetShares,
4890
HgfsServerPolicy_GetSharesInit,
4891
HgfsServerPolicy_GetSharesCleanup,
4892
DIRECTORY_SEARCH_TYPE_BASE,
4900
* If we're outside the Tools, find out if we're to compute the minimum
4901
* values across all shares, or the maximum values.
4903
infoType = VOLUME_INFO_TYPE_MIN;
4906
char *volumeInfoType = Config_GetString("min",
4907
"tools.hgfs.volumeInfoType");
4908
if (!Str_Strcasecmp(volumeInfoType, "max")) {
4909
infoType = VOLUME_INFO_TYPE_MAX;
4911
free(volumeInfoType);
4916
* Now go through all shares and get share paths on the server.
4917
* Then retrieve space info for each share's volume.
4920
while ((dent = HgfsGetSearchResult(handle, session, offset,
4922
char const *sharePath;
4923
size_t sharePathLen;
4924
uint64 currentFreeBytes = 0;
4925
uint64 currentTotalBytes = 0;
4928
length = strlen(dent->d_name);
4931
* Now that the server is passing '.' and ".." around as dents, we
4932
* need to make sure to handle them properly. In particular, they
4933
* should be ignored within QueryVolume, as they're not real shares.
4935
if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {
4936
LOG(4, ("%s: Skipping fake share %s\n", __FUNCTION__,
4943
* The above check ignores '.' and '..' so we do not include them in
4944
* the share count here.
4949
* Check permission on the share and get the share path. It is not
4950
* fatal if these do not succeed. Instead we ignore the failures
4951
* (apart from logging them) until we have processed all shares. Only
4952
* then do we check if there were any failures; if all shares failed
4953
* to process then we bail out with an error code.
4956
nameStatus = HgfsServerPolicy_GetSharePath(dent->d_name, length,
4957
HGFS_OPEN_MODE_READ_ONLY,
4961
if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
4962
LOG(4, ("%s: No such share or access denied\n", __FUNCTION__));
4963
if (0 == firstErr) {
4964
firstErr = HgfsPlatformConvertFromNameStatus(nameStatus);
4971
* Pick the drive with amount of space available and return that
4972
* according to different volume info type.
4976
if (!HgfsServerStatFs(sharePath, sharePathLen,
4977
¤tFreeBytes, ¤tTotalBytes)) {
4978
LOG(4, ("%s: error getting volume information\n",
4980
if (0 == firstErr) {
4981
firstErr = HGFS_ERROR_IO;
4988
* Pick the drive with amount of space available and return that
4989
* according to different volume info type.
4992
case VOLUME_INFO_TYPE_MIN:
4993
if ((outFreeBytes > currentFreeBytes) || firstShare) {
4995
outFreeBytes = currentFreeBytes;
4996
outTotalBytes = currentTotalBytes;
4999
case VOLUME_INFO_TYPE_MAX:
5000
if ((outFreeBytes < currentFreeBytes)) {
5001
outFreeBytes = currentFreeBytes;
5002
outTotalBytes = currentTotalBytes;
5009
if (!HgfsRemoveSearch(handle, session)) {
5010
LOG(4, ("%s: could not close search on base\n", __FUNCTION__));
5012
if (shares == failed) {
5013
if (firstErr != 0) {
5015
* We failed to query any of the shares. We return the error]
5016
* from the first share failure.
5020
/* No shares but no error, return zero for sizes and success. */
5023
case HGFS_NAME_STATUS_COMPLETE:
5025
LOG(4,("%s: querying path %s\n", __FUNCTION__, utf8Name));
5026
success = HgfsServerStatFs(utf8Name, utf8NameLen,
5027
&outFreeBytes, &outTotalBytes);
5030
LOG(4, ("%s: error getting volume information\n", __FUNCTION__));
5031
status = HGFS_ERROR_IO;
5035
LOG(4,("%s: file access check failed\n", __FUNCTION__));
5036
status = HgfsPlatformConvertFromNameStatus(nameStatus);
5039
*freeBytes = outFreeBytes;
5040
*totalBytes = outTotalBytes;
5047
*-----------------------------------------------------------------------------
5049
* HgfsServerQueryVolume --
5051
* Handle a Query Volume request.
5053
* Right now we only handle the volume space request. Call Wiper library
5054
* to get the volume information.
5055
* It is possible that shared folders can belong to different volumes on
5056
* the server. If this is the case, default to return the space information
5057
* of the volume that has the least amount of the available space, but it's
5058
* configurable with a config option (tools.hgfs.volumeInfoType). 2 possible
5059
* options, min and max.
5067
*-----------------------------------------------------------------------------
5071
HgfsServerQueryVolume(HgfsInputParam *input) // IN: Input params
5073
HgfsInternalStatus status;
5074
size_t replyPayloadSize = 0;
5077
size_t fileNameLength;
5083
HGFS_ASSERT_INPUT(input);
5085
if (HgfsUnpackQueryVolumeRequest(input->payload, input->payloadSize, input->op,
5086
&useHandle, &fileName,
5087
&fileNameLength, &caseFlags, &file)) {
5089
* We don't yet support file handle for this operation.
5090
* Clients should retry using the file name.
5093
LOG(4, ("%s: Doesn't support file handle.\n", __FUNCTION__));
5094
status = HGFS_ERROR_INVALID_PARAMETER;
5096
status = HgfsQueryVolume(input->session, fileName, fileNameLength, caseFlags,
5097
&freeBytes, &totalBytes);
5098
if (HGFS_ERROR_SUCCESS == status) {
5099
if (!HgfsPackQueryVolumeReply(input->packet, input->metaPacket,
5100
input->op, freeBytes, totalBytes,
5101
&replyPayloadSize, input->session)) {
5102
status = HGFS_ERROR_INTERNAL;
5107
status = HGFS_ERROR_PROTOCOL;
5110
HgfsServerCompleteRequest(status, replyPayloadSize, input);
5115
*-----------------------------------------------------------------------------
5117
* HgfsSymlinkCreate --
5119
* Platform independent function that verifies whether symbolic link creation
5120
* is allowed for the specific shared folder and then calls platform specific
5121
* HgfsPlatformSymlinkCreate to do the actual job.
5125
* Non-zero on failure.
5130
*-----------------------------------------------------------------------------
5134
HgfsSymlinkCreate(HgfsSessionInfo *session, // IN: session info,
5135
char *srcFileName, // IN: symbolic link file name
5136
uint32 srcFileNameLength, // IN: symbolic link name length
5137
uint32 srcCaseFlags, // IN: symlink case flags
5138
char *trgFileName, // IN: symbolic link target name
5139
uint32 trgFileNameLength, // IN: target name length
5140
uint32 trgCaseFlags) // IN: target case flags
5142
HgfsShareInfo shareInfo;
5143
HgfsInternalStatus status = 0;
5144
HgfsNameStatus nameStatus;
5145
HgfsShareOptions configOptions;
5146
char *localSymlinkName = NULL;
5147
size_t localSymlinkNameLen;
5148
char localTargetName[HGFS_PACKET_MAX];
5151
* It is now safe to read the symlink file name and the
5152
* "targetName" field
5155
nameStatus = HgfsServerGetShareInfo(srcFileName,
5160
&localSymlinkNameLen);
5161
if (nameStatus == HGFS_NAME_STATUS_COMPLETE) {
5162
if (shareInfo.writePermissions ) {
5163
/* Get the config options. */
5164
nameStatus = HgfsServerPolicy_GetShareOptions(srcFileName, srcFileNameLength,
5166
if (nameStatus == HGFS_NAME_STATUS_COMPLETE) {
5167
/* Prohibit symlink ceation if symlink following is enabled. */
5168
if (HgfsServerPolicy_IsShareOptionSet(configOptions, HGFS_SHARE_FOLLOW_SYMLINKS)) {
5169
status = HGFS_ERROR_ACCESS_DENIED;
5172
LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, srcFileName));
5173
status = HgfsPlatformConvertFromNameStatus(nameStatus);
5176
status = HgfsPlatformFileExists(localSymlinkName);
5178
if (status == HGFS_ERROR_FILE_NOT_FOUND) {
5179
status = HGFS_ERROR_ACCESS_DENIED;
5182
status = HGFS_ERROR_FILE_EXIST;
5184
LOG(4, ("%s: failed access check, error %d\n", __FUNCTION__, status));
5187
LOG(4, ("%s: symlink name access check failed\n", __FUNCTION__));
5188
status = HgfsPlatformConvertFromNameStatus(nameStatus);
5190
if (HGFS_ERROR_SUCCESS == status) {
5191
/* Convert from CPName-lite to normal and NUL-terminate. */
5192
memcpy(localTargetName, trgFileName, trgFileNameLength);
5193
CPNameLite_ConvertFrom(localTargetName, trgFileNameLength, DIRSEPC);
5194
localTargetName[trgFileNameLength] = '\0';
5196
status = HgfsPlatformSymlinkCreate(localSymlinkName, localTargetName);
5199
free(localSymlinkName);
5205
*-----------------------------------------------------------------------------
5207
* HgfsServerSymlinkCreate --
5209
* Handle a SymlinkCreate request.
5217
*-----------------------------------------------------------------------------
5221
HgfsServerSymlinkCreate(HgfsInputParam *input) // IN: Input params
5223
HgfsInternalStatus status;
5226
size_t srcFileNameLength;
5227
uint32 srcCaseFlags;
5231
size_t trgFileNameLength;
5232
uint32 trgCaseFlags;
5234
size_t replyPayloadSize = 0;
5236
HGFS_ASSERT_INPUT(input);
5238
if (HgfsUnpackSymlinkCreateRequest(input->payload, input->payloadSize, input->op,
5239
&srcUseHandle, &srcFileName,
5240
&srcFileNameLength, &srcCaseFlags, &srcFile,
5241
&trgUseHandle, &trgFileName,
5242
&trgFileNameLength, &trgCaseFlags, &trgFile)) {
5244
* We don't yet support file handle for this operation.
5245
* Clients should retry using the file name.
5247
if (srcUseHandle || trgUseHandle) {
5248
LOG(4, ("%s: Doesn't support file handle.\n", __FUNCTION__));
5249
status = HGFS_ERROR_INVALID_PARAMETER;
5251
status = HgfsSymlinkCreate(input->session, srcFileName, srcFileNameLength,
5252
srcCaseFlags, trgFileName, trgFileNameLength,
5254
if (HGFS_ERROR_SUCCESS == status) {
5255
if (!HgfsPackSymlinkCreateReply(input->packet, input->metaPacket, input->op,
5256
&replyPayloadSize, input->session)) {
5257
status = HGFS_ERROR_INTERNAL;
5262
status = HGFS_ERROR_PROTOCOL;
5265
HgfsServerCompleteRequest(status, replyPayloadSize, input);
5270
*-----------------------------------------------------------------------------
5272
* HgfsServerSearchOpen --
5274
* Handle a search open request.
5282
*-----------------------------------------------------------------------------
5286
HgfsServerSearchOpen(HgfsInputParam *input) // IN: Input params
5288
HgfsInternalStatus status;
5289
size_t replyPayloadSize = 0;
5291
uint32 dirNameLength;
5292
uint32 caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
5294
HgfsNameStatus nameStatus;
5295
HgfsShareInfo shareInfo;
5296
char *baseDir = NULL;
5299
HGFS_ASSERT_INPUT(input);
5301
if (HgfsUnpackSearchOpenRequest(input->payload, input->payloadSize, input->op,
5302
&dirName, &dirNameLength, &caseFlags)) {
5303
nameStatus = HgfsServerGetShareInfo(dirName, dirNameLength, caseFlags, &shareInfo,
5304
&baseDir, &baseDirLen);
5305
status = HgfsPlatformSearchDir(nameStatus, dirName, dirNameLength, caseFlags,
5306
&shareInfo, baseDir, baseDirLen,
5307
input->session, &search);
5308
if (HGFS_ERROR_SUCCESS == status) {
5309
if (!HgfsPackSearchOpenReply(input->packet, input->metaPacket, input->op, search,
5310
&replyPayloadSize, input->session)) {
5311
status = HGFS_ERROR_INTERNAL;
5315
status = HGFS_ERROR_PROTOCOL;
5318
HgfsServerCompleteRequest(status, replyPayloadSize, input);
5323
*-----------------------------------------------------------------------------
5325
* HgfsValidateRenameFile --
5327
* Validates if the file can can participate in rename process either as
5328
* as a source or as a target.
5331
* HGFS_ERROR_SUCCESS if rename operation is allowed.
5332
* Appropriate error code otherwise.
5335
* Allcates locaFileName which must be freed by the caller.
5337
*-----------------------------------------------------------------------------
5341
HgfsValidateRenameFile(Bool useHandle, // IN:
5342
HgfsHandle fileHandle, // IN:
5343
char *cpName, // IN:
5344
size_t cpNameLength, // IN:
5345
uint32 caseFlags, // IN:
5346
HgfsSessionInfo *session, // IN: Session info
5347
fileDesc* descr, // OUT:
5348
HgfsShareInfo *shareInfo, // OUT:
5349
char **localFileName, // OUT:
5350
size_t *localNameLength) // OUT:
5352
HgfsInternalStatus status;
5353
Bool sharedFolderOpen = FALSE;
5354
HgfsServerLock serverLock = HGFS_LOCK_NONE;
5355
HgfsNameStatus nameStatus;
5359
status = HgfsPlatformGetFd(fileHandle, session, FALSE, descr);
5361
if (HGFS_ERROR_SUCCESS != status) {
5362
LOG(4, ("%s: could not map cached handle %d, error %u\n",
5363
__FUNCTION__, fileHandle, status));
5364
} else if (!HgfsHandle2FileNameMode(fileHandle, session, &shareInfo->writePermissions,
5365
&shareInfo->readPermissions, localFileName,
5368
* HgfsPlatformRename requires valid source file name even when file handle
5370
* Also the name will be required to update the nodes on a successful
5373
LOG(4, ("%s: could not get file name for fd %d\n", __FUNCTION__,
5375
status = HGFS_ERROR_INVALID_HANDLE;
5376
} else if (HgfsHandleIsSharedFolderOpen(fileHandle, session, &sharedFolderOpen) &&
5378
LOG(4, ("%s: Cannot rename shared folder\n", __FUNCTION__));
5379
status = HGFS_ERROR_ACCESS_DENIED;
5382
nameStatus = HgfsServerGetShareInfo(cpName,
5388
if (HGFS_NAME_STATUS_COMPLETE != nameStatus) {
5389
LOG(4, ("%s: access check failed\n", __FUNCTION__));
5390
status = HgfsPlatformConvertFromNameStatus(nameStatus);
5391
} else if (HgfsServerIsSharedFolderOnly(cpName, cpNameLength)) {
5392
/* Guest OS is not allowed to rename shared folder. */
5393
LOG(4, ("%s: Cannot rename shared folder\n", __FUNCTION__));
5394
status = HGFS_ERROR_ACCESS_DENIED;
5396
status = HGFS_ERROR_SUCCESS;
5400
ASSERT(*localFileName != NULL || HGFS_ERROR_SUCCESS != status);
5402
if (HGFS_ERROR_SUCCESS == status) {
5403
if (HgfsFileHasServerLock(*localFileName, session, &serverLock, descr)) {
5405
* XXX: Before renaming the file, check to see if we are holding
5406
* an oplock on both the old and new files. If one of them is oplocked, and
5407
* we commence with the rename, we'll trigger an oplock break that'll
5408
* deadlock us. The client should be smart enough to break necessary oplocks
5409
* on the source and target files before calling rename, so we'll return
5413
LOG (4, ("%s: File has an outstanding oplock. Client "
5414
"should remove this oplock and try again.\n", __FUNCTION__));
5415
status = HGFS_ERROR_PATH_BUSY;
5424
*-----------------------------------------------------------------------------
5426
* HgfsServerRename --
5428
* Handle a Rename request.
5430
* Simply converts the new and old names to local filenames, calls
5431
* platform specific function to rename/move the file, and returns an
5432
* appropriate response to the driver.
5440
*-----------------------------------------------------------------------------
5444
HgfsServerRename(HgfsInputParam *input) // IN: Input params
5446
char *utf8OldName = NULL;
5447
size_t utf8OldNameLen;
5448
char *utf8NewName = NULL;
5449
size_t utf8NewNameLen;
5451
size_t cpOldNameLen;
5453
size_t cpNewNameLen;
5454
HgfsInternalStatus status;
5455
fileDesc srcFileDesc;
5456
fileDesc targetFileDesc;
5458
HgfsHandle targetFile;
5459
HgfsRenameHint hints;
5460
uint32 oldCaseFlags;
5461
uint32 newCaseFlags;
5462
HgfsShareInfo shareInfo;
5463
size_t replyPayloadSize = 0;
5465
HGFS_ASSERT_INPUT(input);
5467
if (HgfsUnpackRenameRequest(input->payload, input->payloadSize, input->op, &cpOldName,
5468
&cpOldNameLen, &cpNewName, &cpNewNameLen,
5469
&hints, &srcFile, &targetFile, &oldCaseFlags,
5471
status = HgfsValidateRenameFile((hints & HGFS_RENAME_HINT_USE_SRCFILE_DESC) != 0,
5481
if (HGFS_ERROR_SUCCESS == status) {
5483
* Renaming a file requires both read and write permssions for the
5485
* However the error code must be different depending on the existence
5486
* of the file with the same name.
5488
if (!shareInfo.writePermissions || !shareInfo.readPermissions) {
5489
status = HgfsPlatformFileExists(utf8OldName);
5490
if (HGFS_ERROR_SUCCESS == status) {
5491
status = HGFS_ERROR_ACCESS_DENIED;
5493
LOG(4, ("HgfsServerRename: failed access check, error %d\n", status));
5496
HgfsValidateRenameFile((hints & HGFS_RENAME_HINT_USE_TARGETFILE_DESC) != 0,
5506
if (HGFS_ERROR_SUCCESS == status) {
5508
* Renaming a file requires both read and write permssions for
5509
* the target directory.
5510
* However the error code must be different depending on the existence
5511
* of the target directory - if the destination directory exists then
5512
* ERROR_ACCESS_DENIED should be returned regardless if the destination
5515
if (!shareInfo.writePermissions || !shareInfo.readPermissions) {
5516
status = HgfsPlatformFileExists(utf8NewName);
5517
if (HGFS_ERROR_SUCCESS == status ||
5518
HGFS_ERROR_FILE_NOT_FOUND == status) {
5519
status = HGFS_ERROR_ACCESS_DENIED;
5521
LOG(4, ("HgfsServerRename: failed access check, error %d\n", status));
5527
status = HGFS_ERROR_PROTOCOL;
5530
/* If all pre-conditions are met go ahead with actual rename. */
5531
if (HGFS_ERROR_SUCCESS == status) {
5532
status = HgfsPlatformRename(utf8OldName, srcFileDesc, utf8NewName,
5533
targetFileDesc, hints);
5534
if (HGFS_ERROR_SUCCESS == status) {
5535
/* Update all file nodes that refer to this file to contain the new name. */
5536
HgfsUpdateNodeNames(utf8OldName, utf8NewName, input->session);
5537
if (!HgfsPackRenameReply(input->packet, input->metaPacket, input->op,
5538
&replyPayloadSize, input->session)) {
5539
status = HGFS_ERROR_INTERNAL;
5547
HgfsServerCompleteRequest(status, replyPayloadSize, input);
5552
*-----------------------------------------------------------------------------
5554
* HgfsServerCreateDir --
5556
* Handle a CreateDir request.
5558
* Simply converts to the local filename, calls platform specific
5559
* code to create a directory, and returns an appropriate response to the driver.
5567
*-----------------------------------------------------------------------------
5571
HgfsServerCreateDir(HgfsInputParam *input) // IN: Input params
5573
HgfsInternalStatus status;
5574
HgfsNameStatus nameStatus;
5575
HgfsCreateDirInfo info;
5578
size_t replyPayloadSize = 0;
5579
HgfsShareInfo shareInfo;
5581
HGFS_ASSERT_INPUT(input);
5583
if (HgfsUnpackCreateDirRequest(input->payload, input->payloadSize,
5584
input->op, &info)) {
5585
nameStatus = HgfsServerGetShareInfo(info.cpName, info.cpNameSize, info.caseFlags,
5586
&shareInfo, &utf8Name, &utf8NameLen);
5587
if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
5590
LOG(4, ("%s: making dir \"%s\"", __FUNCTION__, utf8Name));
5592
* For read-only shares we must never attempt to create a directory.
5593
* However the error code must be different depending on the existence
5594
* of the file with the same name.
5596
if (shareInfo.writePermissions) {
5597
status = HgfsPlatformCreateDir(&info, utf8Name);
5598
if (HGFS_ERROR_SUCCESS == status) {
5599
if (!HgfsPackCreateDirReply(input->packet, input->metaPacket, info.requestType,
5600
&replyPayloadSize, input->session)) {
5601
status = HGFS_ERROR_PROTOCOL;
5605
status = HgfsPlatformFileExists(utf8Name);
5606
if (HGFS_ERROR_SUCCESS == status) {
5607
status = HGFS_ERROR_FILE_EXIST;
5608
} else if (HGFS_ERROR_FILE_NOT_FOUND == status) {
5609
status = HGFS_ERROR_ACCESS_DENIED;
5614
* Check if the name does not exist - the share was not found.
5615
* Then it could one of two things: the share was removed/disabled;
5616
* or we could be in the root share itself and have a new name.
5617
* To return the correct error, if we are in the root share,
5618
* we must check the open mode too - creation of new files/folders
5619
* should fail access denied, for anything else "not found" is acceptable.
5621
if (nameStatus == HGFS_NAME_STATUS_DOES_NOT_EXIST) {
5622
if (HgfsServerIsSharedFolderOnly(info.cpName,
5624
nameStatus = HGFS_NAME_STATUS_ACCESS_DENIED;
5625
LOG(4, ("%s: New file creation in share root not allowed\n", __FUNCTION__));
5627
LOG(4, ("%s: Shared folder not found\n", __FUNCTION__));
5630
LOG(4, ("%s: Shared folder access error %u\n", __FUNCTION__, nameStatus));
5633
status = HgfsPlatformConvertFromNameStatus(nameStatus);
5637
status = HGFS_ERROR_PROTOCOL;
5640
HgfsServerCompleteRequest(status, replyPayloadSize, input);
5645
*-----------------------------------------------------------------------------
5647
* HgfsServerDeleteFile --
5649
* Handle a Delete File request.
5651
* Simply converts to the local filename, calls DeleteFile on the
5652
* file or calls the Windows native API Delete, and returns an
5653
* appropriate response to the driver.
5655
* Enforcing read-only shares restrictions
5663
*-----------------------------------------------------------------------------
5667
HgfsServerDeleteFile(HgfsInputParam *input) // IN: Input params
5671
HgfsServerLock serverLock = HGFS_LOCK_NONE;
5674
HgfsDeleteHint hints = 0;
5675
HgfsInternalStatus status;
5676
HgfsNameStatus nameStatus;
5678
size_t replyPayloadSize = 0;
5679
HgfsShareInfo shareInfo;
5681
HGFS_ASSERT_INPUT(input);
5683
if (HgfsUnpackDeleteRequest(input->payload, input->payloadSize, input->op, &cpName,
5684
&cpNameSize, &hints, &file, &caseFlags)) {
5685
if (hints & HGFS_DELETE_HINT_USE_FILE_DESC) {
5686
status = HgfsPlatformDeleteFileByHandle(file, input->session);
5688
char *utf8Name = NULL;
5691
nameStatus = HgfsServerGetShareInfo(cpName, cpNameSize, caseFlags, &shareInfo,
5692
&utf8Name, &utf8NameLen);
5693
if (nameStatus == HGFS_NAME_STATUS_COMPLETE) {
5695
* Deleting a file needs both read and write permssions.
5696
* However the error code must be different depending on the existence
5697
* of the file with the same name.
5699
if (!shareInfo.writePermissions || !shareInfo.readPermissions) {
5700
status = HgfsPlatformFileExists(utf8Name);
5701
if (HGFS_ERROR_SUCCESS == status) {
5702
status = HGFS_ERROR_ACCESS_DENIED;
5704
LOG(4, ("HgfsServerDeleteFile: failed access check, error %d\n", status));
5705
} else if (HgfsFileHasServerLock(utf8Name, input->session, &serverLock,
5708
* XXX: If the file has an oplock, the client should have broken it on
5709
* its own by now. Sorry!
5711
LOG (4, ("%s: File has an outstanding oplock. Client should "
5712
"remove this oplock and try again.\n", __FUNCTION__));
5713
status = HGFS_ERROR_PATH_BUSY;
5715
LOG(4, ("%s: deleting \"%s\"\n", __FUNCTION__, utf8Name));
5716
status = HgfsPlatformDeleteFileByName(utf8Name);
5720
LOG(4, ("%s: Shared folder does not exist.\n", __FUNCTION__));
5721
status = HgfsPlatformConvertFromNameStatus(nameStatus);
5724
if (HGFS_ERROR_SUCCESS == status) {
5725
if (!HgfsPackDeleteReply(input->packet, input->metaPacket, input->op,
5726
&replyPayloadSize, input->session)) {
5727
status = HGFS_ERROR_INTERNAL;
5731
status = HGFS_ERROR_PROTOCOL;
5734
HgfsServerCompleteRequest(status, replyPayloadSize, input);
5739
*-----------------------------------------------------------------------------
5741
* HgfsServerDeleteDir --
5743
* Handle a Delete Dir request.
5745
* Simply converts to the local filename, calls RemoveDirectory on the
5746
* directory or Windows native API delete if we have a valid handle,
5747
* and returns an appropriate response to the driver.
5755
*-----------------------------------------------------------------------------
5759
HgfsServerDeleteDir(HgfsInputParam *input) // IN: Input params
5763
HgfsInternalStatus status;
5764
HgfsNameStatus nameStatus;
5766
HgfsDeleteHint hints = 0;
5768
Bool sharedFolderOpen = FALSE;
5770
size_t replyPayloadSize = 0;
5771
HgfsShareInfo shareInfo;
5773
HGFS_ASSERT_INPUT(input);
5775
if (HgfsUnpackDeleteRequest(input->payload, input->payloadSize, input->op, &cpName,
5776
&cpNameSize, &hints, &file, &caseFlags)) {
5777
if (hints & HGFS_DELETE_HINT_USE_FILE_DESC) {
5779
status = HgfsPlatformGetFd(file, input->session, FALSE, &fileDesc);
5781
if (HGFS_ERROR_SUCCESS == status) {
5782
if (HgfsHandleIsSharedFolderOpen(file, input->session, &sharedFolderOpen) &&
5784
LOG(4, ("%s: Cannot delete shared folder\n", __FUNCTION__));
5785
status = HGFS_ERROR_ACCESS_DENIED;
5787
status = HgfsPlatformDeleteDirByHandle(file, input->session);
5788
if (HGFS_ERROR_SUCCESS != status) {
5789
LOG(4, ("%s: error deleting directory %d: %d\n", __FUNCTION__,
5794
LOG(4, ("%s: could not map cached handle %u, error %u\n",
5795
__FUNCTION__, file, status));
5798
char *utf8Name = NULL;
5801
nameStatus = HgfsServerGetShareInfo(cpName, cpNameSize, caseFlags, &shareInfo,
5802
&utf8Name, &utf8NameLen);
5803
if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
5805
/* Guest OS is not allowed to delete shared folder. */
5806
if (HgfsServerIsSharedFolderOnly(cpName, cpNameSize)){
5807
LOG(4, ("%s: Cannot delete shared folder\n", __FUNCTION__));
5808
status = HGFS_ERROR_ACCESS_DENIED;
5809
} else if (!shareInfo.writePermissions || !shareInfo.readPermissions) {
5811
* Deleting a directory requires both read and write permissions.
5812
* However the error code must be different depending on the existence
5813
* of the file with the same name.
5815
status = HgfsPlatformFileExists(utf8Name);
5816
if (HGFS_ERROR_SUCCESS == status) {
5817
status = HGFS_ERROR_ACCESS_DENIED;
5819
LOG(4, ("HgfsServerDeleteDir: failed access check, error %d\n", status));
5821
LOG(4, ("%s: removing \"%s\"\n", __FUNCTION__, utf8Name));
5822
status = HgfsPlatformDeleteDirByName(utf8Name);
5826
LOG(4, ("%s: access check failed\n", __FUNCTION__));
5827
status = HgfsPlatformConvertFromNameStatus(nameStatus);
5830
if (HGFS_ERROR_SUCCESS == status) {
5831
if (!HgfsPackDeleteReply(input->packet, input->metaPacket, input->op,
5832
&replyPayloadSize, input->session)) {
5833
status = HGFS_ERROR_INTERNAL;
5837
status = HGFS_ERROR_PROTOCOL;
5840
HgfsServerCompleteRequest(status, replyPayloadSize, input);
5845
*-----------------------------------------------------------------------------
5847
* HgfsServerServerLockChange --
5849
* Called by the client when it wants to either acquire an oplock on a file
5850
* that was previously opened, or when it wants to release/downgrade an
5851
* oplock on a file that was previously oplocked.
5859
*-----------------------------------------------------------------------------
5863
HgfsServerServerLockChange(HgfsInputParam *input) // IN: Input params
5866
HGFS_ASSERT_INPUT(input);
5868
HgfsServerCompleteRequest(HGFS_ERROR_NOT_SUPPORTED, 0, input);
5873
*-----------------------------------------------------------------------------
5875
* HgfsServerWriteWin32Stream --
5877
* Handle a write request in the WIN32_STREAM_ID format.
5880
* ERROR_SUCCESS or an appropriate Win32 error code.
5885
*-----------------------------------------------------------------------------
5889
HgfsServerWriteWin32Stream(HgfsInputParam *input) // IN: Input params
5892
HgfsInternalStatus status;
5896
size_t replyPayloadSize = 0;
5897
size_t requiredSize;
5899
HGFS_ASSERT_INPUT(input);
5901
if (HgfsUnpackWriteWin32StreamRequest(input->payload, input->payloadSize, input->op, &file,
5902
&dataToWrite, &requiredSize, &doSecurity)) {
5903
status = HgfsPlatformWriteWin32Stream(file, dataToWrite, (uint32)requiredSize,
5904
doSecurity, &actualSize, input->session);
5905
if (HGFS_ERROR_SUCCESS == status) {
5906
if (!HgfsPackWriteWin32StreamReply(input->packet, input->metaPacket, input->op,
5907
actualSize, &replyPayloadSize,
5909
status = HGFS_ERROR_INTERNAL;
5913
status = HGFS_ERROR_PROTOCOL;
5916
HgfsServerCompleteRequest(status, replyPayloadSize, input);
5921
*-----------------------------------------------------------------------------
5923
* HgfsServerGetattr --
5925
* Handle a Getattr request.
5933
*-----------------------------------------------------------------------------
5937
HgfsServerGetattr(HgfsInputParam *input) // IN: Input params
5940
HgfsAttrHint hints = 0;
5941
HgfsFileAttrInfo attr;
5942
HgfsInternalStatus status = 0;
5943
HgfsNameStatus nameStatus;
5946
char *targetName = NULL;
5947
uint32 targetNameLen = 0;
5948
HgfsHandle file; /* file handle from driver */
5949
uint32 caseFlags = 0;
5950
HgfsShareOptions configOptions;
5951
size_t localNameLen;
5952
HgfsShareInfo shareInfo;
5953
size_t replyPayloadSize = 0;
5955
HGFS_ASSERT_INPUT(input);
5957
if (HgfsUnpackGetattrRequest(input->payload, input->payloadSize, input->op, &attr,
5958
&hints, &cpName, &cpNameSize, &file, &caseFlags)) {
5959
/* Client wants us to reuse an existing handle. */
5960
if (hints & HGFS_ATTR_HINT_USE_FILE_DESC) {
5964
status = HgfsPlatformGetFd(file, input->session, FALSE, &fd);
5965
if (HGFS_ERROR_SUCCESS == status) {
5966
status = HgfsPlatformGetattrFromFd(fd, input->session, &attr);
5968
LOG(4, ("%s: Could not get file descriptor\n", __FUNCTION__));
5973
* Depending on whether this file/dir is real or virtual, either
5974
* forge its attributes or look them up in the actual filesystem.
5976
nameStatus = HgfsServerGetShareInfo(cpName, cpNameSize, caseFlags, &shareInfo,
5977
&localName, &localNameLen);
5978
switch (nameStatus) {
5979
case HGFS_NAME_STATUS_INCOMPLETE_BASE:
5981
* This is the base of our namespace; make up fake status for
5985
LOG(4, ("%s: getting attrs for base dir\n", __FUNCTION__));
5986
HgfsPlatformGetDefaultDirAttrs(&attr);
5989
case HGFS_NAME_STATUS_COMPLETE:
5990
/* This is a regular lookup; proceed as usual */
5993
/* Get the config options. */
5994
nameStatus = HgfsServerPolicy_GetShareOptions(cpName, cpNameSize,
5996
if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
5997
status = HgfsPlatformGetattrFromName(localName, configOptions, cpName, &attr,
6000
LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, cpName));
6001
status = HGFS_ERROR_FILE_NOT_FOUND;
6005
if (HGFS_ERROR_SUCCESS == status &&
6006
!HgfsServerPolicy_CheckMode(HGFS_OPEN_MODE_READ_ONLY,
6007
shareInfo.writePermissions,
6008
shareInfo.readPermissions)) {
6009
status = HGFS_ERROR_ACCESS_DENIED;
6010
} else if (status != HGFS_ERROR_SUCCESS) {
6012
* If it is a dangling share server should not return
6013
* HGFS_ERROR_FILE_NOT_FOUND
6014
* to the client because it causes confusion: a name that is returned
6015
* by directory enumeration should not produce "name not found"
6017
* Replace it with a more appropriate error code: no such device.
6019
if (status == HGFS_ERROR_FILE_NOT_FOUND &&
6020
HgfsIsShareRoot(cpName, cpNameSize)) {
6021
status = HGFS_ERROR_IO;
6027
status = HgfsPlatformHandleIncompleteName(nameStatus, &attr);
6029
targetNameLen = targetName ? strlen(targetName) : 0;
6032
if (HGFS_ERROR_SUCCESS == status) {
6033
if (!HgfsPackGetattrReply(input->packet, input->metaPacket, &attr, targetName,
6034
targetNameLen, &replyPayloadSize, input->session)) {
6035
status = HGFS_ERROR_INTERNAL;
6039
status = HGFS_ERROR_PROTOCOL;
6042
HgfsServerCompleteRequest(status, replyPayloadSize, input);
6047
*-----------------------------------------------------------------------------
6049
* HgfsServerSetattr --
6051
* Handle a Setattr request.
6059
*-----------------------------------------------------------------------------
6063
HgfsServerSetattr(HgfsInputParam *input) // IN: Input params
6065
HgfsInternalStatus status = HGFS_ERROR_SUCCESS;
6066
HgfsNameStatus nameStatus;
6067
HgfsFileAttrInfo attr;
6069
size_t cpNameSize = 0;
6070
HgfsAttrHint hints = 0;
6071
HgfsOpenMode shareMode;
6072
uint32 caseFlags = 0;
6073
HgfsShareInfo shareInfo;
6075
size_t replyPayloadSize = 0;
6077
HGFS_ASSERT_INPUT(input);
6079
if (HgfsUnpackSetattrRequest(input->payload, input->payloadSize, input->op, &attr,
6080
&hints, &cpName, &cpNameSize, &file, &caseFlags)) {
6081
/* Client wants us to reuse an existing handle. */
6082
if (hints & HGFS_ATTR_HINT_USE_FILE_DESC) {
6083
if (HgfsHandle2ShareMode(file, input->session, &shareMode)) {
6084
if (HGFS_OPEN_MODE_READ_ONLY != shareMode) {
6085
status = HgfsPlatformSetattrFromFd(file, input->session, &attr, hints);
6087
status = HGFS_ERROR_ACCESS_DENIED;
6090
LOG(4, ("%s: could not get share mode fd %d\n", __FUNCTION__,
6092
status = HGFS_ERROR_INVALID_HANDLE;
6094
} else { /* Client wants us to open a new handle for this operation. */
6095
char *utf8Name = NULL;
6098
nameStatus = HgfsServerGetShareInfo(cpName, cpNameSize, caseFlags, &shareInfo,
6099
&utf8Name, &utf8NameLen);
6100
if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
6102
HgfsServerLock serverLock = HGFS_LOCK_NONE;
6103
HgfsShareOptions configOptions;
6106
* XXX: If the client has an oplock on this file, it must reuse the
6107
* handle for the oplocked node (or break the oplock) prior to making
6108
* a setattr request. Fail this request.
6110
if (!HgfsServerPolicy_CheckMode(HGFS_OPEN_MODE_WRITE_ONLY,
6111
shareInfo.writePermissions,
6112
shareInfo.readPermissions)) {
6113
status = HGFS_ERROR_ACCESS_DENIED;
6114
} else if (HGFS_NAME_STATUS_COMPLETE !=
6115
HgfsServerPolicy_GetShareOptions(cpName, cpNameSize,
6117
LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, cpName));
6118
status = HGFS_ERROR_FILE_NOT_FOUND;
6119
} else if (HgfsFileHasServerLock(utf8Name, input->session, &serverLock, &hFile)) {
6120
LOG(4, ("%s: An open, oplocked handle exists for "
6121
"this file. The client should retry with that handle\n",
6123
status = HGFS_ERROR_PATH_BUSY;
6125
status = HgfsPlatformSetattrFromName(utf8Name, &attr, configOptions, hints);
6129
LOG(4, ("%s: file not found.\n", __FUNCTION__));
6130
status = HgfsPlatformConvertFromNameStatus(nameStatus);
6134
if (HGFS_ERROR_SUCCESS == status) {
6135
if (!HgfsPackSetattrReply(input->packet, input->metaPacket, attr.requestType,
6136
&replyPayloadSize, input->session)) {
6137
status = HGFS_ERROR_INTERNAL;
6141
status = HGFS_ERROR_PROTOCOL;
6144
HgfsServerCompleteRequest(status, replyPayloadSize, input);
6149
*-----------------------------------------------------------------------------
6151
* HgfsServerValidateOpenParameters --
6153
* Performs sanity check of the input parameters.
6156
* HGFS_ERROR_SUCCESS if the parameters are valid.
6157
* Appropriate error code otherwise.
6162
*-----------------------------------------------------------------------------
6165
static HgfsInternalStatus
6166
HgfsServerValidateOpenParameters(HgfsFileOpenInfo *openInfo, // IN/OUT: openfile info
6167
Bool *denyCreatingFile, // OUT: No new files
6168
int *followSymlinks) // OUT: Host resolves link
6171
HgfsInternalStatus status;
6173
*followSymlinks = 0;
6174
*denyCreatingFile = FALSE;
6176
if ((openInfo->mask & HGFS_OPEN_VALID_MODE)) {
6177
HgfsNameStatus nameStatus;
6178
/* It is now safe to read the file name. */
6179
nameStatus = HgfsServerGetShareInfo(openInfo->cpName,
6180
openInfo->cpNameSize,
6181
openInfo->caseFlags,
6182
&openInfo->shareInfo,
6183
&openInfo->utf8Name,
6185
if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
6186
if (openInfo->mask & HGFS_OPEN_VALID_FLAGS) {
6187
HgfsOpenFlags savedOpenFlags = openInfo->flags;
6189
if (HgfsServerCheckOpenFlagsForShare(openInfo, &openInfo->flags)) {
6190
HgfsShareOptions configOptions;
6192
/* Get the config options. */
6193
nameStatus = HgfsServerPolicy_GetShareOptions(openInfo->cpName,
6194
openInfo->cpNameSize,
6196
if (nameStatus == HGFS_NAME_STATUS_COMPLETE) {
6198
HgfsServerPolicy_IsShareOptionSet(configOptions,
6199
HGFS_SHARE_FOLLOW_SYMLINKS);
6200
*denyCreatingFile = savedOpenFlags != openInfo->flags;
6201
status = HGFS_ERROR_SUCCESS;
6203
LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, openInfo->cpName));
6204
*denyCreatingFile = TRUE;
6205
status = HGFS_ERROR_FILE_NOT_FOUND;
6208
/* Incompatible open mode with share mode. */
6209
status = HGFS_STATUS_ACCESS_DENIED;
6212
status = HGFS_ERROR_PROTOCOL;
6216
* Check if the name does not exist - the share was not found.
6217
* Then it could one of two things: the share was removed/disabled;
6218
* or we could be in the root share itself and have a new name.
6219
* To return the correct error, if we are in the root share,
6220
* we must check the open mode too - creation of new files/folders
6221
* should fail access denied, for anything else "not found" is acceptable.
6223
if (nameStatus == HGFS_NAME_STATUS_DOES_NOT_EXIST) {
6224
if ((openInfo->mask & HGFS_OPEN_VALID_FLAGS &&
6225
(openInfo->flags == HGFS_OPEN_CREATE ||
6226
openInfo->flags == HGFS_OPEN_CREATE_SAFE ||
6227
openInfo->flags == HGFS_OPEN_CREATE_EMPTY)) &&
6228
HgfsServerIsSharedFolderOnly(openInfo->cpName,
6229
openInfo->cpNameSize)) {
6230
nameStatus = HGFS_NAME_STATUS_ACCESS_DENIED;
6231
LOG(4, ("%s: New file creation in share root not allowed\n", __FUNCTION__));
6233
LOG(4, ("%s: Shared folder not found\n", __FUNCTION__));
6236
LOG(4, ("%s: Shared folder access error %u\n", __FUNCTION__, nameStatus));
6238
status = HgfsPlatformConvertFromNameStatus(nameStatus);
6241
LOG(4, ("%s: filename or mode not provided\n", __FUNCTION__));
6242
status = HGFS_ERROR_PROTOCOL;
6249
*-----------------------------------------------------------------------------
6253
* Handle an Open request.
6261
*-----------------------------------------------------------------------------
6265
HgfsServerOpen(HgfsInputParam *input) // IN: Input params
6267
HgfsInternalStatus status;
6269
HgfsLocalId localId;
6270
HgfsFileOpenInfo openInfo;
6272
HgfsServerLock serverLock = HGFS_LOCK_NONE;
6273
size_t replyPayloadSize = 0;
6275
HGFS_ASSERT_INPUT(input);
6277
if (HgfsUnpackOpenRequest(input->payload, input->payloadSize, input->op, &openInfo)) {
6279
Bool denyCreatingFile;
6281
status = HgfsServerValidateOpenParameters(&openInfo, &denyCreatingFile,
6283
if (HGFS_ERROR_SUCCESS == status) {
6284
ASSERT(openInfo.utf8Name);
6285
LOG(4, ("%s: opening \"%s\", mode %u, flags %u, perms %u%u%u%u attr %u\n",
6286
__FUNCTION__, openInfo.utf8Name, openInfo.mode,
6287
openInfo.mask & HGFS_OPEN_VALID_FLAGS ? openInfo.flags : 0,
6288
(openInfo.mask & HGFS_OPEN_VALID_SPECIAL_PERMS) ?
6289
openInfo.specialPerms : 0,
6290
(openInfo.mask & HGFS_OPEN_VALID_OWNER_PERMS) ?
6291
openInfo.ownerPerms : 0,
6292
(openInfo.mask & HGFS_OPEN_VALID_GROUP_PERMS) ?
6293
openInfo.groupPerms : 0,
6294
(openInfo.mask & HGFS_OPEN_VALID_OTHER_PERMS) ?
6295
openInfo.otherPerms : 0,
6296
openInfo.mask & HGFS_OPEN_VALID_FILE_ATTR ? (uint32)openInfo.attr : 0));
6298
* XXX: Before opening the file, see if we already have this file opened on
6299
* the server with an oplock on it. If we do, we must fail the new open
6300
* request, otherwise we will trigger an oplock break that the guest cannot
6301
* handle at this time (since the HGFS server is running in the context of
6302
* the vcpu thread), and we'll deadlock.
6304
* Until we overcome this limitation via Crosstalk, we will be extra smart
6305
* in the client drivers so as to prevent open requests on handles that
6306
* already have an oplock. And the server will protect itself like so.
6308
* XXX: With some extra effort, we could allow a second open for read here,
6309
* since that won't break a shared oplock, but the clients should already
6310
* realize that the second open can be avoided via sharing handles, too.
6312
if (!HgfsFileHasServerLock(openInfo.utf8Name, input->session, &serverLock,
6314
/* See if the name is valid, and if so add it and return the handle. */
6315
status = HgfsPlatformValidateOpen(&openInfo, followSymlinks, input->session,
6316
&localId, &newHandle);
6317
if (status == HGFS_ERROR_SUCCESS) {
6318
ASSERT(newHandle >= 0);
6321
* Open succeeded, so make new node and return its handle. If we fail,
6322
* it's almost certainly an internal server error.
6325
if (HgfsCreateAndCacheFileNode(&openInfo, &localId, newHandle,
6326
FALSE, input->session)) {
6327
if (!HgfsPackOpenReply(input->packet, input->metaPacket, &openInfo,
6328
&replyPayloadSize, input->session)) {
6329
status = HGFS_ERROR_INTERNAL;
6332
} else if (denyCreatingFile && HGFS_ERROR_FILE_NOT_FOUND == status) {
6333
status = HGFS_ERROR_ACCESS_DENIED;
6336
status = HGFS_ERROR_PATH_BUSY;
6338
free(openInfo.utf8Name);
6341
status = HGFS_ERROR_PROTOCOL;
6344
HgfsServerCompleteRequest(status, replyPayloadSize, input);
6349
*-----------------------------------------------------------------------------
6351
* HgfsGetDirEntry --
6353
* Gets a directory entry at specified offset.
6361
*-----------------------------------------------------------------------------
6364
static HgfsInternalStatus
6365
HgfsGetDirEntry(HgfsHandle hgfsSearchHandle,
6366
uint32 requestedOffset,
6368
HgfsShareOptions configOptions,
6369
HgfsSessionInfo *session,
6370
HgfsFileAttrInfo *attr,
6374
HgfsInternalStatus status;
6375
DirectoryEntry *dent;
6377
dent = HgfsGetSearchResult(hgfsSearchHandle, session, requestedOffset, FALSE);
6379
unsigned int length;
6382
size_t sharePathLen;
6384
HgfsServerLock serverLock = HGFS_LOCK_NONE;
6387
length = strlen(dent->d_name);
6389
/* Each type of search gets a dent's attributes in a different way. */
6390
switch (search->type) {
6391
case DIRECTORY_SEARCH_TYPE_DIR:
6394
* Construct the UTF8 version of the full path to the file, and call
6395
* HgfsGetattrFromName to get the attributes of the file.
6397
fullNameLen = search->utf8DirLen + 1 + length;
6398
fullName = (char *)malloc(fullNameLen + 1);
6400
memcpy(fullName, search->utf8Dir, search->utf8DirLen);
6401
fullName[search->utf8DirLen] = DIRSEPC;
6402
memcpy(&fullName[search->utf8DirLen + 1], dent->d_name, length + 1);
6404
LOG(4, ("%s: about to stat \"%s\"\n", __FUNCTION__, fullName));
6407
* XXX: It is unreasonable to make the caller either 1) pass existing
6408
* handles for directory objects as part of the SearchRead, or 2)
6409
* prior to calling SearchRead on a directory, break all oplocks on
6410
* that directory's objects.
6412
* To compensate for that, if we detect that this directory object
6413
* has an oplock, we'll quietly reuse the handle. Note that this
6414
* requires clients who take out an exclusive oplock to open a
6415
* handle with read as well as write access, otherwise we'll fail
6416
* further down in HgfsStat.
6418
* XXX: We could open a new handle safely if its a shared oplock.
6419
* But isn't this handle sharing always desirable?
6421
if (HgfsFileHasServerLock(fullName, session, &serverLock, &fileDesc)) {
6422
LOG(4, ("%s: Reusing existing oplocked handle "
6423
"to avoid oplock break deadlock\n", __FUNCTION__));
6424
status = HgfsPlatformGetattrFromFd(fileDesc, session, attr);
6426
status = HgfsPlatformGetattrFromName(fullName, configOptions,
6427
search->utf8ShareName, attr, NULL);
6430
if (HGFS_ERROR_SUCCESS != status) {
6431
HgfsOp savedOp = attr->requestType;
6432
LOG(4, ("%s: stat FAILED %s (%d)\n", __FUNCTION__, fullName, status));
6433
memset(attr, 0, sizeof *attr);
6434
attr->requestType = savedOp;
6435
attr->type = HGFS_FILE_TYPE_REGULAR;
6440
status = HGFS_ERROR_SUCCESS;
6442
LOG(4, ("%s: could not allocate space for \"%s\\%s\"\n",
6443
__FUNCTION__, search->utf8Dir, dent->d_name));
6444
status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
6448
case DIRECTORY_SEARCH_TYPE_BASE:
6451
* For a search enumerating all shares, give the default attributes
6452
* for '.' and ".." (which aren't really shares anyway). Each real
6453
* share gets resolved into its full path, and gets its attributes
6454
* via HgfsGetattrFromName.
6456
if (strcmp(dent->d_name, ".") == 0 ||
6457
strcmp(dent->d_name, "..") == 0) {
6458
LOG(4, ("%s: assigning %s default attributes\n",
6459
__FUNCTION__, dent->d_name));
6460
HgfsPlatformGetDefaultDirAttrs(attr);
6461
status = HGFS_ERROR_SUCCESS;
6463
HgfsNameStatus nameStatus;
6465
/* Check permission on the share and get the share path */
6467
HgfsServerPolicy_GetSharePath(dent->d_name, length,
6468
HGFS_OPEN_MODE_READ_ONLY,
6470
(char const **)&sharePath);
6471
if (nameStatus == HGFS_NAME_STATUS_COMPLETE) {
6474
* Server needs to produce list of shares that is consistent with
6475
* the list defined in UI. If a share can't be accessed because of
6476
* problems on the host, the server still enumerates it and
6477
* returns to the client.
6480
* XXX: We will open a new handle for this, but it should be safe
6481
* from oplock-induced deadlock because these are all directories,
6482
* and thus cannot have oplocks placed on them.
6484
status = HgfsPlatformGetattrFromName(sharePath, configOptions,
6485
dent->d_name, attr, NULL);
6488
* For some reason, Windows marks drives as hidden and system. So
6489
* if one of the top level shared folders is mapped to a drive
6490
* letter (like C:\), then GetFileAttributesEx() will return hidden
6491
* and system attributes for that drive. We don't want that
6492
* since we want the users to see all top level shared folders.
6493
* Even in the case when the top level shared folder is mapped
6494
* to a non-drive hidden/system directory, we still want to display
6495
* it to the user. So make sure that system and hidden attributes
6497
* Note, that for network shares this doesn't apply, since each
6498
* top level network share is a separate mount point that doesn't
6499
* have such attributes. So when we finally have per share
6500
* mounting, this hack will go away.
6504
attr->flags &= ~(HGFS_ATTR_HIDDEN | HGFS_ATTR_SYSTEM);
6506
if (HGFS_ERROR_SUCCESS != status) {
6508
* The dent no longer exists. Log the event.
6511
LOG(4, ("%s: stat FAILED\n", __FUNCTION__));
6512
status = HGFS_ERROR_SUCCESS;
6515
LOG(4, ("%s: No such share or access denied\n", __FUNCTION__));
6516
status = HgfsPlatformConvertFromNameStatus(nameStatus);
6520
case DIRECTORY_SEARCH_TYPE_OTHER:
6523
* The POSIX implementation of HgfsSearchOpen could not have created
6524
* this kind of search.
6526
#if !defined(_WIN32)
6530
* All "other" searches get the default attributes. This includes
6531
* an enumeration of drive, and the root enumeration (which contains
6532
* a "drive" dent and a "unc" dent).
6534
HgfsPlatformGetDefaultDirAttrs(attr);
6542
* We need to unescape the name before sending it back to the client
6544
if (HGFS_ERROR_SUCCESS == status) {
6545
*entryName = strdup(dent->d_name);
6546
*nameLength = HgfsEscape_Undo(dent->d_name, length + 1);
6547
LOG(4, ("%s: dent name is \"%s\" len = %"FMTSZ"u\n", __FUNCTION__,
6548
*entryName, *nameLength));
6552
LOG(4, ("%s: error %d getting dent\n", __FUNCTION__, status));
6557
/* End of directory entries marker. */
6560
status = HGFS_ERROR_SUCCESS;
6567
*-----------------------------------------------------------------------------
6569
* HgfsServerSearchRead --
6571
* Handle a "Search Read" request.
6579
*-----------------------------------------------------------------------------
6583
HgfsServerSearchRead(HgfsInputParam *input) // IN: Input params
6585
uint32 requestedOffset;
6586
HgfsFileAttrInfo attr;
6587
HgfsInternalStatus status;
6588
HgfsNameStatus nameStatus;
6589
HgfsHandle hgfsSearchHandle;
6591
HgfsShareOptions configOptions = 0;
6592
size_t replyPayloadSize = 0;
6596
HGFS_ASSERT_INPUT(input);
6598
if (HgfsUnpackSearchReadRequest(input->payload, input->payloadSize, input->op, &attr,
6599
&hgfsSearchHandle, &requestedOffset)) {
6600
LOG(4, ("%s: read search #%u, offset %u\n", __FUNCTION__,
6601
hgfsSearchHandle, requestedOffset));
6602
if (HgfsGetSearchCopy(hgfsSearchHandle, input->session, &search)) {
6603
/* Get the config options. */
6604
status = HGFS_ERROR_SUCCESS;
6605
if (search.utf8ShareNameLen != 0) {
6606
nameStatus = HgfsServerPolicy_GetShareOptions(search.utf8ShareName,
6607
search.utf8ShareNameLen,
6609
if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
6610
LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__,
6611
search.utf8ShareName));
6612
status = HGFS_ERROR_FILE_NOT_FOUND;
6616
if (HGFS_ERROR_SUCCESS == status) {
6617
status = HgfsGetDirEntry(hgfsSearchHandle, requestedOffset, &search,
6618
configOptions, input->session, &attr, &entryName,
6620
if (HGFS_ERROR_SUCCESS == status) {
6621
if (!HgfsPackSearchReadReply(input->packet, input->metaPacket, entryName,
6622
nameLength, &attr, &replyPayloadSize,
6624
status = HGFS_ERROR_INTERNAL;
6630
free(search.utf8Dir);
6631
free(search.utf8ShareName);
6633
LOG(4, ("%s: handle %u is invalid\n", __FUNCTION__, hgfsSearchHandle));
6634
status = HGFS_ERROR_INVALID_HANDLE;
6637
status = HGFS_ERROR_PROTOCOL;
6640
HgfsServerCompleteRequest(status, replyPayloadSize, input);
6645
*-----------------------------------------------------------------------------
6647
* HgfsServerCreateSession --
6649
* Handle a "Create session" request.
6657
*-----------------------------------------------------------------------------
6661
HgfsServerCreateSession(HgfsInputParam *input) // IN: Input params
6663
size_t replyPayloadSize = 0;
6664
HgfsCreateSessionInfo info;
6665
HgfsInternalStatus status;
6667
HGFS_ASSERT_INPUT(input);
6669
if (HgfsUnpackCreateSessionRequest(input->payload, input->payloadSize,
6670
input->op, &info)) {
6671
LOG(4, ("%s: create session\n", __FUNCTION__));
6672
if (info.maxPacketSize < input->session->maxPacketSize) {
6673
input->session->maxPacketSize = info.maxPacketSize;
6675
if (HgfsPackCreateSessionReply(input->packet, input->metaPacket,
6676
&replyPayloadSize, input->session)) {
6677
HgfsServerSessionGet(input->session);
6678
status = HGFS_ERROR_SUCCESS;
6680
status = HGFS_ERROR_INTERNAL;
6683
status = HGFS_ERROR_PROTOCOL;
6686
HgfsServerCompleteRequest(status, replyPayloadSize, input);
6691
*-----------------------------------------------------------------------------
6693
* HgfsServerDestroySession --
6695
* Handle a "Destroy session" request.
6703
*-----------------------------------------------------------------------------
6707
HgfsServerDestroySession(HgfsInputParam *input) // IN: Input params
6709
HGFS_ASSERT_INPUT(input);
6711
HgfsServerCompleteRequest(HGFS_ERROR_SUCCESS, 0, input);
6712
HgfsServerSessionPut(input->session);