~n-muench/ubuntu/oneiric/open-vm-tools/open-vm-tools-august.merge

« back to all changes in this revision

Viewing changes to lib/hgfsServer/hgfsServer.c

  • Committer: Bazaar Package Importer
  • Author(s): Nate Muench
  • Date: 2010-09-06 21:06:01 UTC
  • mfrom: (2.4.19 sid)
  • Revision ID: james.westby@ubuntu.com-20100906210601-gxxy30e5roil4srt
Tags: 2010.06.16-268169-3ubuntu1
* Merge from Debian testing (LP: #632101), remaining changes:
  - Recommend open-vm-toolbox in open-vm-tools.
  - Rediffing vsock.patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include "cpNameLite.h"
26
26
#include "hgfsServerInt.h"
27
27
#include "hgfsServerPolicy.h"
 
28
#include "hgfsUtil.h"
 
29
#include "hgfsVirtualDir.h"
 
30
#include "hgfsEscape.h"
28
31
#include "codeset.h"
29
32
#include "config.h"
30
33
#include "file.h"
32
35
#include "wiper.h"
33
36
#include "hgfsDirNotify.h"
34
37
#include "hgfsTransport.h"
 
38
#include "userlock.h"
 
39
#include "poll.h"
 
40
#include "libMutexRank.h"
 
41
#include "vm_basic_asm.h"
35
42
 
36
43
#if defined(_WIN32)
37
44
#include <io.h>
66
73
#define HGFS_ASSERT_CLIENT(op)
67
74
#endif
68
75
 
 
76
#define HGFS_ASSERT_INPUT(input) ASSERT(input && input->packet && input->metaPacket && \
 
77
                                        input->session && \
 
78
                                        (!input->payloadSize || input->payload))
69
79
 
70
80
/*
71
81
 * Define this to enable an ASSERT if server gets an op lower than
155
165
 
156
166
/* Session related callbacks. */
157
167
static void HgfsServerSessionReceive(HgfsPacket *packet,
158
 
                                     void *clientData,
159
 
                                     HgfsReceiveFlags flags);
 
168
                                     void *clientData);
160
169
static Bool HgfsServerSessionConnect(void *transportData,
161
170
                                     HgfsServerChannelCallbacks *channelCbTable,
162
171
                                     void **clientData);
180
189
 
181
190
static Bool hgfsChangeNotificationSupported = FALSE;
182
191
 
 
192
/*
 
193
 *    Limit payload to 16M + header.
 
194
 *    This limit ensures that list of shared pages fits into VMCI datagram.
 
195
 *    Client may impose a lower limit in create session request.
 
196
 */
 
197
#define MAX_SERVER_PACKET_SIZE_V4         (0x1000000 + sizeof(HgfsHeader))
183
198
 
184
199
/* Local functions. */
185
200
 
223
238
static HgfsFileNode *HgfsHandle2FileNode(HgfsHandle handle,
224
239
                                         HgfsSessionInfo *session);
225
240
static void HgfsServerExitSessionInternal(HgfsSessionInfo *session);
226
 
static Bool HgfsValidatePacket(char const *packetIn, size_t packetSize);
227
 
static void HgfsPackReplyHeaderV4(HgfsInternalStatus status,
228
 
                                  uint32 payloadSize,
229
 
                                  HgfsHeader const *packetIn,
230
 
                                  HgfsHeader *header);
 
241
static Bool HgfsIsShareRoot(char const *cpName, size_t cpNameSize);
 
242
static void HgfsServerCompleteRequest(HgfsInternalStatus status,
 
243
                                      size_t replyPayloadSize,
 
244
                                      HgfsInputParam *input);
 
245
 
 
246
/*
 
247
 * Opcode handlers
 
248
 */
 
249
 
 
250
static void HgfsServerOpen(HgfsInputParam *input);
 
251
static void HgfsServerRead(HgfsInputParam *input);
 
252
static void HgfsServerWrite(HgfsInputParam *input);
 
253
static void HgfsServerSearchOpen(HgfsInputParam *input);
 
254
static void HgfsServerSearchRead(HgfsInputParam *input);
 
255
static void HgfsServerGetattr(HgfsInputParam *input);
 
256
static void HgfsServerSetattr(HgfsInputParam *input);
 
257
static void HgfsServerCreateDir(HgfsInputParam *input);
 
258
static void HgfsServerDeleteFile(HgfsInputParam *input);
 
259
static void HgfsServerDeleteDir(HgfsInputParam *input);
 
260
static void HgfsServerRename(HgfsInputParam *input);
 
261
static void HgfsServerQueryVolume(HgfsInputParam *input);
 
262
static void HgfsServerSymlinkCreate(HgfsInputParam *input);
 
263
static void HgfsServerServerLockChange(HgfsInputParam *input);
 
264
static void HgfsServerWriteWin32Stream(HgfsInputParam *input);
 
265
static void HgfsServerCreateSession(HgfsInputParam *input);
 
266
static void HgfsServerDestroySession(HgfsInputParam *input);
 
267
static void HgfsServerClose(HgfsInputParam *input);
 
268
static void HgfsServerSearchClose(HgfsInputParam *input);
 
269
 
231
270
 
232
271
/*
233
272
 *----------------------------------------------------------------------------
245
284
 *----------------------------------------------------------------------------
246
285
 */
247
286
 
248
 
static void
 
287
void
249
288
HgfsServerSessionGet(HgfsSessionInfo *session)   // IN: session context
250
289
{
251
290
   ASSERT(session);
498
537
   Bool found = FALSE;
499
538
   HgfsFileNode *fileNode = NULL;
500
539
 
501
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
540
   MXUser_AcquireExclLock(session->nodeArrayLock);
502
541
   fileNode = HgfsHandle2FileNode(handle, session);
503
542
   if (fileNode == NULL) {
504
543
      goto exit;
511
550
   found = TRUE;
512
551
 
513
552
exit:
514
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
553
   MXUser_ReleaseExclLock(session->nodeArrayLock);
515
554
 
516
555
   return found;
517
556
}
543
582
   Bool found = FALSE;
544
583
   HgfsFileNode *fileNode = NULL;
545
584
 
546
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
585
   MXUser_AcquireExclLock(session->nodeArrayLock);
547
586
   fileNode = HgfsHandle2FileNode(handle, session);
548
587
   if (fileNode == NULL) {
549
588
      goto exit;
553
592
   found = TRUE;
554
593
 
555
594
exit:
556
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
595
   MXUser_ReleaseExclLock(session->nodeArrayLock);
557
596
 
558
597
   return found;
559
598
}
587
626
 
588
627
   ASSERT(localId);
589
628
 
590
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
629
   MXUser_AcquireExclLock(session->nodeArrayLock);
591
630
   fileNode = HgfsHandle2FileNode(handle, session);
592
631
   if (fileNode == NULL) {
593
632
      goto exit;
599
638
   found = TRUE;
600
639
 
601
640
exit:
602
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
641
   MXUser_ReleaseExclLock(session->nodeArrayLock);
603
642
 
604
643
   return found;
605
644
}
635
674
 
636
675
   ASSERT(lock);
637
676
 
638
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
677
   MXUser_AcquireExclLock(session->nodeArrayLock);
639
678
   fileNode = HgfsHandle2FileNode(handle, session);
640
679
   if (fileNode == NULL) {
641
680
      goto exit;
645
684
   found = TRUE;
646
685
 
647
686
exit:
648
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
687
   MXUser_ReleaseExclLock(session->nodeArrayLock);
649
688
 
650
689
   return found;
651
690
#else
684
723
   ASSERT(session);
685
724
   ASSERT(session->nodeArray);
686
725
 
687
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
726
   MXUser_AcquireExclLock(session->nodeArrayLock);
688
727
 
689
728
   for (i = 0; i < session->numNodes; i++) {
690
729
      existingFileNode = &session->nodeArray[i];
696
735
      }
697
736
   }
698
737
 
699
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
738
   MXUser_ReleaseExclLock(session->nodeArrayLock);
700
739
 
701
740
   return found;
702
741
}
732
771
      return found;
733
772
   }
734
773
 
735
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
774
   MXUser_AcquireExclLock(session->nodeArrayLock);
736
775
 
737
776
   existingFileNode = HgfsHandle2FileNode(handle, session);
738
777
   if (existingFileNode == NULL) {
745
784
   found = (nameStatus == HGFS_NAME_STATUS_COMPLETE);
746
785
 
747
786
exit_unlock:
748
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
787
   MXUser_ReleaseExclLock(session->nodeArrayLock);
749
788
 
750
789
   return found;
751
790
}
814
853
      return found;
815
854
   }
816
855
 
817
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
856
   MXUser_AcquireExclLock(session->nodeArrayLock);
818
857
 
819
858
   existingFileNode = HgfsHandle2FileNode(handle, session);
820
859
   if (existingFileNode == NULL) {
833
872
   found = TRUE;
834
873
 
835
874
exit_unlock:
836
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
875
   MXUser_ReleaseExclLock(session->nodeArrayLock);
837
876
 
838
877
   *fileName = name;
839
878
   *fileNameSize = nameSize;
875
914
   ASSERT(session);
876
915
   ASSERT(session->nodeArray);
877
916
 
878
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
917
   MXUser_AcquireExclLock(session->nodeArrayLock);
879
918
 
880
919
   for (i = 0; i < session->numNodes; i++) {
881
920
      HgfsFileNode *existingFileNode = &session->nodeArray[i];
890
929
      }
891
930
   }
892
931
 
893
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
932
   MXUser_ReleaseExclLock(session->nodeArrayLock);
894
933
 
895
934
   return found;
896
935
#else
929
968
 
930
969
   ASSERT(copy);
931
970
 
932
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
971
   MXUser_AcquireExclLock(session->nodeArrayLock);
933
972
 
934
973
   original = HgfsHandle2FileNode(handle, session);
935
974
   if (original == NULL) {
960
999
   found = TRUE;
961
1000
 
962
1001
exit:
963
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
1002
   MXUser_ReleaseExclLock(session->nodeArrayLock);
964
1003
 
965
1004
   return found;
966
1005
}
993
1032
 
994
1033
   ASSERT(sequentialOpen);
995
1034
 
996
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
1035
   MXUser_AcquireExclLock(session->nodeArrayLock);
997
1036
 
998
1037
   node = HgfsHandle2FileNode(handle, session);
999
1038
   if (node == NULL) {
1004
1043
   success = TRUE;
1005
1044
 
1006
1045
exit:
1007
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
1046
   MXUser_ReleaseExclLock(session->nodeArrayLock);
1008
1047
 
1009
1048
   return success;
1010
1049
}
1037
1076
 
1038
1077
   ASSERT(sharedFolderOpen);
1039
1078
 
1040
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
1079
   MXUser_AcquireExclLock(session->nodeArrayLock);
1041
1080
 
1042
1081
   node = HgfsHandle2FileNode(handle, session);
1043
1082
   if (node == NULL) {
1048
1087
   success = TRUE;
1049
1088
 
1050
1089
exit:
1051
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
1090
   MXUser_ReleaseExclLock(session->nodeArrayLock);
1052
1091
 
1053
1092
   return success;
1054
1093
}
1081
1120
   HgfsFileNode *node;
1082
1121
   Bool updated = FALSE;
1083
1122
 
1084
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
1123
   MXUser_AcquireExclLock(session->nodeArrayLock);
1085
1124
 
1086
1125
   node = HgfsHandle2FileNode(handle, session);
1087
1126
   if (node == NULL) {
1093
1132
   updated = TRUE;
1094
1133
 
1095
1134
exit:
1096
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
1135
   MXUser_ReleaseExclLock(session->nodeArrayLock);
1097
1136
 
1098
1137
   return updated;
1099
1138
}
1129
1168
   ASSERT(session);
1130
1169
   ASSERT(session->nodeArray);
1131
1170
 
1132
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
1171
   MXUser_AcquireExclLock(session->nodeArrayLock);
1133
1172
 
1134
1173
   for (i = 0; i < session->numNodes; i++) {
1135
1174
      existingFileNode = &session->nodeArray[i];
1142
1181
      }
1143
1182
   }
1144
1183
 
1145
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
1184
   MXUser_ReleaseExclLock(session->nodeArrayLock);
1146
1185
 
1147
1186
   return updated;
1148
1187
}
1173
1212
   HgfsFileNode *node;
1174
1213
   Bool updated = FALSE;
1175
1214
 
1176
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
1215
   MXUser_AcquireExclLock(session->nodeArrayLock);
1177
1216
 
1178
1217
   node = HgfsHandle2FileNode(handle, session);
1179
1218
   if (node == NULL) {
1186
1225
   updated = TRUE;
1187
1226
 
1188
1227
exit:
1189
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
1228
   MXUser_ReleaseExclLock(session->nodeArrayLock);
1190
1229
 
1191
1230
   return updated;
1192
1231
}
1530
1569
HgfsFreeFileNode(HgfsHandle handle,         // IN: Handle to free
1531
1570
                 HgfsSessionInfo *session)  // IN: Session info
1532
1571
{
1533
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
1572
   MXUser_AcquireExclLock(session->nodeArrayLock);
1534
1573
   HgfsFreeFileNodeInternal(handle, session);
1535
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
1574
   MXUser_ReleaseExclLock(session->nodeArrayLock);
1536
1575
}
1537
1576
 
1538
1577
 
1880
1919
{
1881
1920
   Bool allowed;
1882
1921
 
1883
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
1922
   MXUser_AcquireExclLock(session->nodeArrayLock);
1884
1923
   allowed = session->numCachedLockedNodes < MAX_LOCKED_FILENODES;
1885
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
1924
   MXUser_ReleaseExclLock(session->nodeArrayLock);
1886
1925
 
1887
1926
   return allowed;
1888
1927
}
2079
2118
 
2080
2119
   ASSERT(copy);
2081
2120
 
2082
 
   HGFS_LOCK_ACQUIRE(session->searchArrayLock);
 
2121
   MXUser_AcquireExclLock(session->searchArrayLock);
2083
2122
   original = HgfsSearchHandle2Search(handle, session);
2084
2123
   if (original == NULL) {
2085
2124
      goto exit;
2110
2149
   found = TRUE;
2111
2150
 
2112
2151
exit:
2113
 
   HGFS_LOCK_RELEASE(session->searchArrayLock);
 
2152
   MXUser_ReleaseExclLock(session->searchArrayLock);
2114
2153
 
2115
2154
   return found;
2116
2155
}
2262
2301
   HgfsSearch *search;
2263
2302
   Bool success = FALSE;
2264
2303
 
2265
 
   HGFS_LOCK_ACQUIRE(session->searchArrayLock);
 
2304
   MXUser_AcquireExclLock(session->searchArrayLock);
2266
2305
 
2267
2306
   search = HgfsSearchHandle2Search(handle, session);
2268
2307
   if (search != NULL) {
2270
2309
      success = TRUE;
2271
2310
   }
2272
2311
 
2273
 
   HGFS_LOCK_RELEASE(session->searchArrayLock);
 
2312
   MXUser_ReleaseExclLock(session->searchArrayLock);
2274
2313
 
2275
2314
   return success;
2276
2315
}
2304
2343
   HgfsSearch *search;
2305
2344
   DirectoryEntry *dent = NULL;
2306
2345
 
2307
 
   HGFS_LOCK_ACQUIRE(session->searchArrayLock);
 
2346
   MXUser_AcquireExclLock(session->searchArrayLock);
2308
2347
 
2309
2348
   search = HgfsSearchHandle2Search(handle, session);
2310
2349
   if (search == NULL || search->dents == NULL) {
2360
2399
   }
2361
2400
 
2362
2401
  out:
2363
 
   HGFS_LOCK_RELEASE(session->searchArrayLock);
 
2402
   MXUser_ReleaseExclLock(session->searchArrayLock);
2364
2403
 
2365
2404
   return dent;
2366
2405
}
2444
2483
 
2445
2484
   newBufferLen = strlen(newLocalName);
2446
2485
 
2447
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
2486
   MXUser_AcquireExclLock(session->nodeArrayLock);
2448
2487
 
2449
2488
   for (i = 0; i < session->numNodes; i++) {
2450
2489
      fileNode = &session->nodeArray[i];
2470
2509
      }
2471
2510
   }
2472
2511
 
2473
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
2512
   MXUser_ReleaseExclLock(session->nodeArrayLock);
2474
2513
}
2475
2514
 
2476
2515
 
2491
2530
 *-----------------------------------------------------------------------------
2492
2531
 */
2493
2532
 
2494
 
static HgfsInternalStatus
 
2533
static void
2495
2534
HgfsServerClose(HgfsInputParam *input)  // IN: Input params
2496
2535
{
2497
 
   const char *packetIn = input->metaPacket;
2498
 
   size_t packetSize = input->metaPacketSize;
2499
 
   HgfsSessionInfo *session = input->session;
2500
2536
   HgfsHandle file;
2501
 
   char *packetOut = NULL;
2502
 
   size_t replySize;
2503
 
   HgfsInternalStatus status = 0;
2504
 
   HgfsOp op;
2505
 
 
2506
 
   ASSERT(packetIn);
2507
 
   ASSERT(session);
2508
 
 
2509
 
   if (!HgfsUnpackCloseRequest(packetIn, packetSize, &op, &file)) {
2510
 
      status = HGFS_INTERNAL_STATUS_ERROR;
2511
 
      goto error;
2512
 
   }
2513
 
 
2514
 
   LOG(4, ("%s: close fh %u\n", __FUNCTION__, file));
2515
 
 
2516
 
   if (!HgfsRemoveFromCache(file, session)) {
2517
 
      LOG(4, ("%s: Could not remove the node from cache.\n", __FUNCTION__));
2518
 
      status = HGFS_INTERNAL_STATUS_ERROR;
 
2537
   HgfsInternalStatus status = HGFS_ERROR_SUCCESS;
 
2538
   size_t replyPayloadSize = 0;
 
2539
 
 
2540
   HGFS_ASSERT_INPUT(input);
 
2541
 
 
2542
   if (HgfsUnpackCloseRequest(input->payload, input->payloadSize, input->op, &file)) {
 
2543
 
 
2544
      LOG(4, ("%s: close fh %u\n", __FUNCTION__, file));
 
2545
 
 
2546
      if (!HgfsRemoveFromCache(file, input->session)) {
 
2547
         LOG(4, ("%s: Could not remove the node from cache.\n", __FUNCTION__));
 
2548
         status = HGFS_ERROR_INTERNAL;
 
2549
      } else {
 
2550
         HgfsFreeFileNode(file, input->session);
 
2551
         if (!HgfsPackCloseReply(input->packet, input->metaPacket, input->op,
 
2552
                                 &replyPayloadSize, input->session)) {
 
2553
            status = HGFS_ERROR_INTERNAL;
 
2554
         }
 
2555
      }
2519
2556
   } else {
2520
 
      HgfsFreeFileNode(file, session);
2521
 
   }
2522
 
 
2523
 
   if (!HgfsPackCloseReply(input->packet, packetIn, status, op,
2524
 
                           &packetOut, &replySize, session) ||
2525
 
       !HgfsPacketSend(input->packet, packetOut, replySize, session, 0)) {
2526
 
      status = HGFS_INTERNAL_STATUS_ERROR;
2527
 
      goto error;
2528
 
   }
2529
 
 
2530
 
   return 0;
2531
 
 
2532
 
error:
2533
 
   HSPU_PutReplyPacket(input->packet, session);
2534
 
   return status;
 
2557
      status = HGFS_ERROR_INTERNAL;
 
2558
   }
 
2559
 
 
2560
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
2535
2561
}
2536
2562
 
2537
2563
 
2552
2578
 *-----------------------------------------------------------------------------
2553
2579
 */
2554
2580
 
2555
 
static HgfsInternalStatus
 
2581
static void
2556
2582
HgfsServerSearchClose(HgfsInputParam *input)  // IN: Input params
2557
2583
{
2558
 
   const char *packetIn = input->metaPacket;
2559
 
   size_t packetSize = input->metaPacketSize;
2560
 
   HgfsSessionInfo *session = input->session;
2561
2584
   HgfsHandle search;
2562
 
   char *packetOut = NULL;
2563
 
   size_t replySize;
2564
 
   HgfsInternalStatus status = 0;
2565
 
   HgfsOp op;
2566
 
 
2567
 
   ASSERT(packetIn);
2568
 
   ASSERT(session);
2569
 
 
2570
 
   if (!HgfsUnpackSearchCloseRequest(packetIn, packetSize, &op, &search)) {
2571
 
      status = HGFS_INTERNAL_STATUS_ERROR;
2572
 
      goto error;
2573
 
   }
2574
 
 
2575
 
   LOG(4, ("%s: close search #%u\n", __FUNCTION__, search));
2576
 
 
2577
 
   if (!HgfsRemoveSearch(search, session)) {
2578
 
      /* Invalid handle */
2579
 
      LOG(4, ("%s: invalid handle %u\n", __FUNCTION__, search));
2580
 
      status = HGFS_INTERNAL_STATUS_ERROR;
2581
 
      goto error;
2582
 
   }
2583
 
 
2584
 
   if (!HgfsPackSearchCloseReply(input->packet, packetIn, status, op,
2585
 
                                 &packetOut, &replySize, session) ||
2586
 
       !HgfsPacketSend(input->packet, packetOut, replySize, session, 0)) {
2587
 
      status = HGFS_INTERNAL_STATUS_ERROR;
2588
 
      goto error;
2589
 
   }
2590
 
 
2591
 
   return 0;
2592
 
 
2593
 
error:
2594
 
   HSPU_PutReplyPacket(input->packet, session);
2595
 
   return status;
 
2585
   HgfsInternalStatus status;
 
2586
   size_t replyPayloadSize = 0;
 
2587
 
 
2588
   HGFS_ASSERT_INPUT(input);
 
2589
 
 
2590
   if (HgfsUnpackSearchCloseRequest(input->payload, input->payloadSize, input->op,
 
2591
                                    &search)) {
 
2592
 
 
2593
      LOG(4, ("%s: close search #%u\n", __FUNCTION__, search));
 
2594
 
 
2595
      if (HgfsRemoveSearch(search, input->session)) {
 
2596
         if (HgfsPackSearchCloseReply(input->packet, input->metaPacket, input->op,
 
2597
                                      &replyPayloadSize, input->session)) {
 
2598
            status = HGFS_ERROR_SUCCESS;
 
2599
         } else {
 
2600
            status = HGFS_ERROR_INTERNAL;
 
2601
         }
 
2602
      } else {
 
2603
         /* Invalid handle */
 
2604
         LOG(4, ("%s: invalid handle %u\n", __FUNCTION__, search));
 
2605
         status = HGFS_ERROR_INTERNAL;
 
2606
      }
 
2607
   } else {
 
2608
      status = HGFS_ERROR_INTERNAL;
 
2609
   }
 
2610
 
 
2611
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
2596
2612
}
2597
2613
 
2598
2614
 
2600
2616
 
2601
2617
/* Opcode handlers, indexed by opcode */
2602
2618
static struct {
2603
 
   HgfsInternalStatus
2604
 
   (*handler)(HgfsInputParam *input);
2605
 
 
 
2619
   void (*handler)(HgfsInputParam *input);
2606
2620
   /* Minimal size of the request packet */
2607
2621
   unsigned int minReqSize;
 
2622
 
 
2623
   /* How do you process the request {sync, async} ? */
 
2624
   RequestHint reqType;
 
2625
 
2608
2626
} const handlers[] = {
2609
 
   { HgfsServerOpen,             sizeof (HgfsRequestOpen)              },
2610
 
   { HgfsServerRead,             sizeof (HgfsRequestRead)              },
2611
 
   { HgfsServerWrite,            sizeof (HgfsRequestWrite)             },
2612
 
   { HgfsServerClose,            sizeof (HgfsRequestClose)             },
2613
 
   { HgfsServerSearchOpen,       sizeof (HgfsRequestSearchOpen)        },
2614
 
   { HgfsServerSearchRead,       sizeof (HgfsRequestSearchRead)        },
2615
 
   { HgfsServerSearchClose,      sizeof (HgfsRequestSearchClose)       },
2616
 
   { HgfsServerGetattr,          sizeof (HgfsRequestGetattr)           },
2617
 
   { HgfsServerSetattr,          sizeof (HgfsRequestSetattr)           },
2618
 
   { HgfsServerCreateDir,        sizeof (HgfsRequestCreateDir)         },
2619
 
   { HgfsServerDeleteFile,       sizeof (HgfsRequestDelete)            },
2620
 
   { HgfsServerDeleteDir,        sizeof (HgfsRequestDelete)            },
2621
 
   { HgfsServerRename,           sizeof (HgfsRequestRename)            },
2622
 
   { HgfsServerQueryVolume,      sizeof (HgfsRequestQueryVolume)       },
2623
 
 
2624
 
   { HgfsServerOpen,             sizeof (HgfsRequestOpenV2)            },
2625
 
   { HgfsServerGetattr,          sizeof (HgfsRequestGetattrV2)         },
2626
 
   { HgfsServerSetattr,          sizeof (HgfsRequestSetattrV2)         },
2627
 
   { HgfsServerSearchRead,       sizeof (HgfsRequestSearchReadV2)      },
2628
 
   { HgfsServerSymlinkCreate,    sizeof (HgfsRequestSymlinkCreate)     },
2629
 
   { HgfsServerServerLockChange, sizeof (HgfsRequestServerLockChange)  },
2630
 
   { HgfsServerCreateDir,        sizeof (HgfsRequestCreateDirV2)       },
2631
 
   { HgfsServerDeleteFile,       sizeof (HgfsRequestDeleteV2)          },
2632
 
   { HgfsServerDeleteDir,        sizeof (HgfsRequestDeleteV2)          },
2633
 
   { HgfsServerRename,           sizeof (HgfsRequestRenameV2)          },
2634
 
 
2635
 
   { HgfsServerOpen,             HGFS_SIZEOF_OP(HgfsRequestOpenV3)             },
2636
 
   { HgfsServerRead,             HGFS_SIZEOF_OP(HgfsRequestReadV3)             },
2637
 
   { HgfsServerWrite,            HGFS_SIZEOF_OP(HgfsRequestWriteV3)            },
2638
 
   { HgfsServerClose,            HGFS_SIZEOF_OP(HgfsRequestCloseV3)            },
2639
 
   { HgfsServerSearchOpen,       HGFS_SIZEOF_OP(HgfsRequestSearchOpenV3)       },
2640
 
   { HgfsServerSearchRead,       HGFS_SIZEOF_OP(HgfsRequestSearchReadV3)       },
2641
 
   { HgfsServerSearchClose,      HGFS_SIZEOF_OP(HgfsRequestSearchCloseV3)      },
2642
 
   { HgfsServerGetattr,          HGFS_SIZEOF_OP(HgfsRequestGetattrV3)          },
2643
 
   { HgfsServerSetattr,          HGFS_SIZEOF_OP(HgfsRequestSetattrV3)          },
2644
 
   { HgfsServerCreateDir,        HGFS_SIZEOF_OP(HgfsRequestCreateDirV3)        },
2645
 
   { HgfsServerDeleteFile,       HGFS_SIZEOF_OP(HgfsRequestDeleteV3)           },
2646
 
   { HgfsServerDeleteDir,        HGFS_SIZEOF_OP(HgfsRequestDeleteV3)           },
2647
 
   { HgfsServerRename,           HGFS_SIZEOF_OP(HgfsRequestRenameV3)           },
2648
 
   { HgfsServerQueryVolume,      HGFS_SIZEOF_OP(HgfsRequestQueryVolumeV3)      },
2649
 
   { HgfsServerSymlinkCreate,    HGFS_SIZEOF_OP(HgfsRequestSymlinkCreateV3)    },
2650
 
   { HgfsServerServerLockChange, sizeof (HgfsRequestServerLockChange)          },
2651
 
   { HgfsServerWriteWin32Stream, HGFS_SIZEOF_OP(HgfsRequestWriteWin32StreamV3) },
 
2627
   { HgfsServerOpen,             sizeof (HgfsRequestOpen),              REQ_SYNC },
 
2628
   { HgfsServerRead,             sizeof (HgfsRequestRead),              REQ_SYNC },
 
2629
   { HgfsServerWrite,            sizeof (HgfsRequestWrite),             REQ_SYNC },
 
2630
   { HgfsServerClose,            sizeof (HgfsRequestClose),             REQ_SYNC },
 
2631
   { HgfsServerSearchOpen,       sizeof (HgfsRequestSearchOpen),        REQ_SYNC },
 
2632
   { HgfsServerSearchRead,       sizeof (HgfsRequestSearchRead),        REQ_SYNC },
 
2633
   { HgfsServerSearchClose,      sizeof (HgfsRequestSearchClose),       REQ_SYNC },
 
2634
   { HgfsServerGetattr,          sizeof (HgfsRequestGetattr),           REQ_SYNC },
 
2635
   { HgfsServerSetattr,          sizeof (HgfsRequestSetattr),           REQ_SYNC },
 
2636
   { HgfsServerCreateDir,        sizeof (HgfsRequestCreateDir),         REQ_SYNC },
 
2637
   { HgfsServerDeleteFile,       sizeof (HgfsRequestDelete),            REQ_SYNC },
 
2638
   { HgfsServerDeleteDir,        sizeof (HgfsRequestDelete),            REQ_SYNC },
 
2639
   { HgfsServerRename,           sizeof (HgfsRequestRename),            REQ_SYNC },
 
2640
   { HgfsServerQueryVolume,      sizeof (HgfsRequestQueryVolume),       REQ_SYNC },
 
2641
 
 
2642
   { HgfsServerOpen,             sizeof (HgfsRequestOpenV2),            REQ_SYNC },
 
2643
   { HgfsServerGetattr,          sizeof (HgfsRequestGetattrV2),         REQ_SYNC },
 
2644
   { HgfsServerSetattr,          sizeof (HgfsRequestSetattrV2),         REQ_SYNC },
 
2645
   { HgfsServerSearchRead,       sizeof (HgfsRequestSearchReadV2),      REQ_SYNC },
 
2646
   { HgfsServerSymlinkCreate,    sizeof (HgfsRequestSymlinkCreate),     REQ_SYNC },
 
2647
   { HgfsServerServerLockChange, sizeof (HgfsRequestServerLockChange),  REQ_SYNC },
 
2648
   { HgfsServerCreateDir,        sizeof (HgfsRequestCreateDirV2),       REQ_SYNC },
 
2649
   { HgfsServerDeleteFile,       sizeof (HgfsRequestDeleteV2),          REQ_SYNC },
 
2650
   { HgfsServerDeleteDir,        sizeof (HgfsRequestDeleteV2),          REQ_SYNC },
 
2651
   { HgfsServerRename,           sizeof (HgfsRequestRenameV2),          REQ_SYNC },
 
2652
 
 
2653
   { HgfsServerOpen,             HGFS_SIZEOF_OP(HgfsRequestOpenV3),             REQ_SYNC },
 
2654
   { HgfsServerRead,             HGFS_SIZEOF_OP(HgfsRequestReadV3),             REQ_SYNC },
 
2655
   { HgfsServerWrite,            HGFS_SIZEOF_OP(HgfsRequestWriteV3),            REQ_SYNC },
 
2656
   { HgfsServerClose,            HGFS_SIZEOF_OP(HgfsRequestCloseV3),            REQ_SYNC },
 
2657
   { HgfsServerSearchOpen,       HGFS_SIZEOF_OP(HgfsRequestSearchOpenV3),       REQ_SYNC },
 
2658
   { HgfsServerSearchRead,       HGFS_SIZEOF_OP(HgfsRequestSearchReadV3),       REQ_SYNC },
 
2659
   { HgfsServerSearchClose,      HGFS_SIZEOF_OP(HgfsRequestSearchCloseV3),      REQ_SYNC },
 
2660
   { HgfsServerGetattr,          HGFS_SIZEOF_OP(HgfsRequestGetattrV3),          REQ_SYNC },
 
2661
   { HgfsServerSetattr,          HGFS_SIZEOF_OP(HgfsRequestSetattrV3),          REQ_SYNC },
 
2662
   { HgfsServerCreateDir,        HGFS_SIZEOF_OP(HgfsRequestCreateDirV3),        REQ_SYNC },
 
2663
   { HgfsServerDeleteFile,       HGFS_SIZEOF_OP(HgfsRequestDeleteV3),           REQ_SYNC },
 
2664
   { HgfsServerDeleteDir,        HGFS_SIZEOF_OP(HgfsRequestDeleteV3),           REQ_SYNC },
 
2665
   { HgfsServerRename,           HGFS_SIZEOF_OP(HgfsRequestRenameV3),           REQ_SYNC },
 
2666
   { HgfsServerQueryVolume,      HGFS_SIZEOF_OP(HgfsRequestQueryVolumeV3),      REQ_SYNC },
 
2667
   { HgfsServerSymlinkCreate,    HGFS_SIZEOF_OP(HgfsRequestSymlinkCreateV3),    REQ_SYNC },
 
2668
   { HgfsServerServerLockChange, sizeof (HgfsRequestServerLockChange),          REQ_SYNC },
 
2669
   { HgfsServerWriteWin32Stream, HGFS_SIZEOF_OP(HgfsRequestWriteWin32StreamV3), REQ_SYNC },
2652
2670
   /*
2653
 
    * XXX
2654
 
    *    Will be replaced with the real thing when during merge with another outstanding
2655
 
    *    change.
2656
 
    *    For now just set min size big enough so request gets rejected when
2657
 
    *    such request comes from the client.
 
2671
    * Starting from HGFS_OP_CREATE_SESSION_V4 (all V4 commands and above) the
 
2672
    * second field is the minimum size for actual HGFS operational request
 
2673
    * and not the minimum size of operational request with a header.
2658
2674
    */
2659
 
   { NULL, 0xffffff      },   // Implemented in another change
2660
 
   { NULL, 0xffffff      },   // Implemented in another change
2661
 
   { HgfsServerRead,             HGFS_SIZEOF_OP(HgfsRequestReadV3)             },
2662
 
   { HgfsServerWrite,            HGFS_SIZEOF_OP(HgfsRequestWriteV3)            },
 
2675
   { HgfsServerCreateSession,    offsetof(HgfsRequestCreateSessionV4, reserved),   REQ_SYNC},
 
2676
   { HgfsServerDestroySession,   offsetof(HgfsRequestDestroySessionV4, reserved),  REQ_SYNC},
 
2677
   { HgfsServerRead,             sizeof (HgfsRequestReadV3),                       REQ_SYNC},
 
2678
   { HgfsServerWrite,            sizeof (HgfsRequestWriteV3),                      REQ_SYNC},
 
2679
 
2663
2680
};
2664
2681
 
2665
2682
 
2666
2683
/*
2667
2684
 *-----------------------------------------------------------------------------
2668
2685
 *
 
2686
 * HgfsServerCompleteRequest --
 
2687
 *
 
2688
 *    Performs all necessary action which needed for completing HGFS request:
 
2689
 *       1. Sends reply to the guest.
 
2690
 *       2. Release allocated objects, mapped guest memory.
 
2691
 *       3. Dereference objects that were referenced.
 
2692
 *
 
2693
 * Results:
 
2694
 *    None.
 
2695
 *
 
2696
 * Side effects:
 
2697
 *    Reference to Session is dropped.
 
2698
 *
 
2699
 *-----------------------------------------------------------------------------
 
2700
 */
 
2701
 
 
2702
static void
 
2703
HgfsServerCompleteRequest(HgfsInternalStatus status,   // IN: Status of the request
 
2704
                          size_t replyPayloadSize,     // IN: sizeof the reply payload
 
2705
                          HgfsInputParam *input)       // INOUT: request context
 
2706
{
 
2707
   char *packetOut;
 
2708
   size_t replyPacketSize;
 
2709
   size_t replySize;
 
2710
 
 
2711
   HGFS_ASSERT_INPUT(input);
 
2712
 
 
2713
   if (input->v4header) {
 
2714
      HgfsHeader *header;
 
2715
      replySize = sizeof *header + replyPayloadSize;
 
2716
      replyPacketSize = replySize;
 
2717
      header = HSPU_GetReplyPacket(input->packet, &replyPacketSize, input->session);
 
2718
      packetOut = (char *)header;
 
2719
 
 
2720
      ASSERT_DEVEL(header && (replySize <= replyPacketSize));
 
2721
      if (header && (sizeof *header <= replyPacketSize)) {
 
2722
         HgfsPackReplyHeaderV4(status, replyPayloadSize, input->op,
 
2723
                               input->session->sessionId, input->id, header);
 
2724
      }
 
2725
   } else {
 
2726
      HgfsReply *reply;
 
2727
      replySize = sizeof *reply + replyPayloadSize;
 
2728
      replyPacketSize = replySize;
 
2729
      reply = HSPU_GetReplyPacket(input->packet, &replyPacketSize, input->session);
 
2730
      packetOut = (char *)reply;
 
2731
 
 
2732
      ASSERT_DEVEL(reply && (replySize <= replyPacketSize));
 
2733
      if (reply && (sizeof *reply <= replyPacketSize)) {
 
2734
         reply->id = input->id;
 
2735
         reply->status = HgfsConvertFromInternalStatus(status);
 
2736
      }
 
2737
   }
 
2738
   if (!HgfsPacketSend(input->packet, packetOut, replySize, input->session, 0)) {
 
2739
      /* Send failed. Drop the reply. */
 
2740
      LOG(4, ("Error sending reply\n"));
 
2741
   }
 
2742
 
 
2743
   HgfsServerSessionPut(input->session);
 
2744
   free(input);
 
2745
}
 
2746
 
 
2747
 
 
2748
/*
 
2749
 *-----------------------------------------------------------------------------
 
2750
 *
 
2751
 * HgfsServerProcessRequest --
 
2752
 *
 
2753
 *    Dispatch an incoming packet (in packetIn) to a handler function.
 
2754
 *
 
2755
 * Results:
 
2756
 *    None
 
2757
 *
 
2758
 * Side effects:
 
2759
 *    None
 
2760
 *
 
2761
 *-----------------------------------------------------------------------------
 
2762
 */
 
2763
 
 
2764
static void
 
2765
HgfsServerProcessRequest(void *context)
 
2766
{
 
2767
   HgfsInputParam *input = (HgfsInputParam *)context;
 
2768
   if (!input->metaPacket) {
 
2769
      input->metaPacket = HSPU_GetMetaPacket(input->packet,
 
2770
                                             &input->metaPacketSize,
 
2771
                                             input->session);
 
2772
   }
 
2773
   (*handlers[input->op].handler)(input);
 
2774
}
 
2775
 
 
2776
 
 
2777
/*
 
2778
 *-----------------------------------------------------------------------------
 
2779
 *
2669
2780
 * HgfsServerSessionReceive --
2670
2781
 *
2671
2782
 *    Dispatch an incoming packet (in packetIn) to a handler function.
2674
2785
 *    a packet containing only a reply header with error code.
2675
2786
 *
2676
2787
 *    The handler function can send the reply packet either using HgfsPacketSend
2677
 
 *    or HgfsPackAndSendPacket helper functions. This function would return error
2678
 
 *    as a reply if the op handler do not return HGFS_STATUS_SUCCESS.
 
2788
 *    helper functions. This function would return error
 
2789
 *    as a reply if the op handler do not return HGFS_ERROR_SUCCESS.
2679
2790
 *
2680
2791
 *    NOTE: If any op handler needs to keep packetIn around for sending replies
2681
2792
 *    at a later point (possibly in a different thread context), it should
2695
2806
 
2696
2807
static void
2697
2808
HgfsServerSessionReceive(HgfsPacket *packet,      // IN: Hgfs Packet
2698
 
                         void *clientData,        // IN: session info
2699
 
                         HgfsReceiveFlags flags)  // IN: flags to indicate processing
 
2809
                         void *clientData)        // IN: session info
2700
2810
{
2701
2811
   HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
2702
 
   HgfsRequest *request;
2703
 
   HgfsHandle id;
2704
 
   HgfsOp op;
2705
 
   HgfsStatus status;
2706
 
   Bool v4header = FALSE;
2707
 
   HgfsInputParam input;
2708
 
   size_t metaPacketSize;
2709
 
   char *metaPacket;
 
2812
   HgfsInternalStatus status;
 
2813
   HgfsInputParam *input = NULL;
2710
2814
 
2711
2815
   ASSERT(session);
2712
2816
 
2713
2817
   if (session->state == HGFS_SESSION_STATE_CLOSED) {
2714
2818
      LOG(4, ("%s: %d: Received packet after disconnected.\n", __FUNCTION__,
2715
2819
              __LINE__));
2716
 
 
2717
 
      return;
2718
 
   }
2719
 
 
2720
 
   metaPacket = HSPU_GetMetaPacket(packet, &metaPacketSize, session);
2721
 
   request = (HgfsRequest *)metaPacket;
2722
 
   ASSERT_DEVEL(request);
2723
 
   if (!request) {
2724
 
      /*
2725
 
       * How can I return error back to the client, clearly the client is either broken or
2726
 
       * malicious ? We cannot continue from here.
2727
 
       */
2728
 
      return;
2729
 
   }
2730
 
 
2731
 
   /*
2732
 
    * Error out if less than HgfsRequest size.
2733
 
    */
2734
 
   if (metaPacketSize < sizeof *request) {
2735
 
      if (metaPacketSize >= sizeof id) {
2736
 
         id = request->id;
2737
 
      } else {
2738
 
         id = 0;
2739
 
      }
2740
 
      status = HGFS_STATUS_PROTOCOL_ERROR;
2741
 
      ASSERT_DEVEL(0);
2742
 
      goto err;
2743
 
   }
2744
 
 
2745
 
   /* Increment the session's reference count until we send the reply. */
 
2820
      return;
 
2821
   }
 
2822
 
2746
2823
   HgfsServerSessionGet(session);
2747
2824
 
2748
 
   id = request->id;
2749
 
   op = request->op;
2750
 
 
2751
 
   /* If it is a V4 packet then handle it appropriately. */
2752
 
  if (HGFS_V4_LEGACY_OPCODE == op) {
2753
 
      HgfsHeader *header = (HgfsHeader *)metaPacket;
2754
 
      if (metaPacketSize < sizeof *header) {
2755
 
         status = HGFS_STATUS_PROTOCOL_ERROR;
2756
 
         ASSERT_DEVEL(0);
2757
 
         goto err;
2758
 
      }
2759
 
      op = header->op;
2760
 
      v4header = TRUE;
2761
 
   }
2762
 
 
2763
 
   if (!HgfsValidatePacket(metaPacket, metaPacketSize)) {
2764
 
      status = HGFS_STATUS_PROTOCOL_ERROR;
2765
 
      LOG(4, ("%s: %d: Possible BUG! malformed packet.\n", __FUNCTION__,
2766
 
               __LINE__));
2767
 
      goto err;
2768
 
   }
2769
 
 
2770
 
   HGFS_ASSERT_MINIMUM_OP(op);
2771
 
   if (op < sizeof handlers / sizeof handlers[0]) {
2772
 
      if (metaPacketSize >= handlers[op].minReqSize) {
2773
 
         HgfsInternalStatus internalStatus;
2774
 
         input.metaPacket = metaPacket;
2775
 
         input.metaPacketSize = metaPacketSize;
2776
 
         input.session = session;
2777
 
         input.packet = packet;
2778
 
         internalStatus = (*handlers[op].handler)(&input);
2779
 
         status = HgfsConvertFromInternalStatus(internalStatus);
 
2825
   if (!HgfsParseRequest(packet, session, &input, &status)) {
 
2826
      LOG(4, ("%s: %d: Can't generate any response for the guest, just exit.\n ",
 
2827
              __FUNCTION__, __LINE__));
 
2828
      HgfsServerSessionPut(session);
 
2829
      return;
 
2830
   }
 
2831
 
 
2832
   HGFS_ASSERT_MINIMUM_OP(input->op);
 
2833
   if (HGFS_ERROR_SUCCESS == status) {
 
2834
      HGFS_ASSERT_INPUT(input);
 
2835
      if (HgfsValidatePacket(input->metaPacket, input->metaPacketSize, input->v4header) &&
 
2836
          (input->op < ARRAYSIZE(handlers)) &&
 
2837
          (input->metaPacketSize >= handlers[input->op].minReqSize)) {
 
2838
         /* Initial validation passed, process the client request now. */
 
2839
         packet->processedAsync = packet->supportsAsync &&
 
2840
                                  (handlers[input->op].reqType == REQ_ASYNC);
 
2841
         if (packet->processedAsync) {
 
2842
            LOG(4, ("%s: %d: @@Async\n", __FUNCTION__, __LINE__));
 
2843
#ifndef VMX86_TOOLS
 
2844
            /*
 
2845
             * Asynchronous processing is supported by the transport.
 
2846
             * We can release mappings here and reacquire when needed.
 
2847
             */
 
2848
            HSPU_PutMetaPacket(packet, session);
 
2849
            input->metaPacket = NULL;
 
2850
 
 
2851
            /* Remove pending requests during poweroff. */
 
2852
            Poll_Callback(POLL_CS_MAIN,
 
2853
                          POLL_FLAG_REMOVE_AT_POWEROFF,
 
2854
                          HgfsServerProcessRequest,
 
2855
                          input,
 
2856
                          POLL_REALTIME,
 
2857
                          1000,
 
2858
                          NULL);
 
2859
#else
 
2860
            /* Tools code should never process request async. */
 
2861
            ASSERT(0);
 
2862
#endif
 
2863
         } else {
 
2864
            LOG(4, ("%s: %d: ##Sync\n", __FUNCTION__, __LINE__));
 
2865
            HgfsServerProcessRequest(input);
 
2866
         }
2780
2867
      } else {
2781
2868
         /*
2782
2869
          * The input packet is smaller than the minimal size needed for the
2783
2870
          * operation.
2784
2871
          */
2785
 
 
2786
 
         status = HGFS_STATUS_PROTOCOL_ERROR;
2787
 
         LOG(4, ("%s: %d: Possible BUG! Smaller packet.\n", __FUNCTION__,
2788
 
                 __LINE__));
 
2872
         status = HGFS_ERROR_PROTOCOL;
 
2873
         LOG(4, ("%s: %d: Possible BUG! Malformed packet.\n", __FUNCTION__, __LINE__));
2789
2874
      }
2790
 
   } else {
2791
 
      /* Unknown opcode */
2792
 
      status = HGFS_STATUS_PROTOCOL_ERROR;
2793
 
      LOG(4, ("%s: %d: Possible BUG! Invalid opcode.\n", __FUNCTION__,
2794
 
              __LINE__));
2795
2875
   }
2796
 
   HGFS_ASSERT_CLIENT(op);
 
2876
   HGFS_ASSERT_CLIENT(input->op);
2797
2877
 
2798
 
err:
2799
2878
   /* Send error if we fail to process the op. */
2800
 
   if (status != HGFS_STATUS_SUCCESS) {
2801
 
      char *packetOut;
2802
 
      uint32 replySize;
2803
 
      size_t replyPacketSize;
2804
 
      if (v4header) {
2805
 
         HgfsHeader *header;
2806
 
         replyPacketSize = sizeof *header;
2807
 
         header = HSPU_GetReplyPacket(packet, &replyPacketSize, session);
2808
 
         if (!header || sizeof *header > replyPacketSize) {
2809
 
            /*
2810
 
             * Transport should probably check for minimum hgfs packet size.
2811
 
             * How should we send an error back if there is no meta packet ?
2812
 
             */
2813
 
            return;
2814
 
         }
2815
 
         HgfsPackReplyHeaderV4(status, 0, (HgfsHeader *)metaPacket, header);
2816
 
         packetOut = (char *)header;
2817
 
         replySize = sizeof *header;
2818
 
      } else {
2819
 
         HgfsReply *reply;
2820
 
         replyPacketSize = sizeof *reply;
2821
 
         reply = HSPU_GetReplyPacket(packet, &replyPacketSize, session);
2822
 
         if (!reply || sizeof *reply > replyPacketSize) {
2823
 
            /*
2824
 
             * Transport should probably check for minimum hgfs packet size.
2825
 
             * How should we send an error back if there is no meta packet ?
2826
 
             */
2827
 
            return;
2828
 
         }
2829
 
         reply->id = id;
2830
 
         reply->status = status;
2831
 
         packetOut = (char *)reply;
2832
 
         replySize = sizeof *reply;
2833
 
      }
2834
 
      LOG(4, ("Error occured for id = %u\n", (uint32)id));
2835
 
      if (!HgfsPacketSend(packet, packetOut, replySize, session, 0)) {
2836
 
         /* Send failed. Drop the reply. */
2837
 
         HSPU_PutReplyPacket(packet, session);
2838
 
      }
 
2879
   if (HGFS_ERROR_SUCCESS != status) {
 
2880
      LOG(4, ("Error %d occured parsing the packet\n", (uint32)status));
 
2881
      HgfsServerCompleteRequest(status, 0, input);
2839
2882
   }
2840
2883
}
2841
2884
 
2938
2981
/*
2939
2982
 *-----------------------------------------------------------------------------
2940
2983
 *
 
2984
 * HgfsGenerateSessionId --
 
2985
 *
 
2986
 *    Generates unique session id.
 
2987
 *
 
2988
 * Results:
 
2989
 *    Unique 64-bit value.
 
2990
 *
 
2991
 * Side effects:
 
2992
 *    None.
 
2993
 *
 
2994
 *-----------------------------------------------------------------------------
 
2995
 */
 
2996
 
 
2997
static uint64
 
2998
HgfsGenerateSessionId(void)
 
2999
{
 
3000
   return RDTSC();
 
3001
}
 
3002
 
 
3003
 
 
3004
/*
 
3005
 *-----------------------------------------------------------------------------
 
3006
 *
2941
3007
 * HgfsServerSessionConnect --
2942
3008
 *
2943
3009
 *    Initialize a new client session.
2970
3036
    * Initialize all our locks first as these can fail.
2971
3037
    */
2972
3038
 
2973
 
   session->fileIOLock = HGFS_LOCK_NEW("HgfsFileIOLock");
 
3039
   session->fileIOLock = MXUser_CreateExclLock("HgfsFileIOLock",
 
3040
                                               RANK_hgfsFileIOLock);
2974
3041
   if (session->fileIOLock == NULL) {
2975
3042
      free(session);
2976
3043
      LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
2978
3045
      return FALSE;
2979
3046
   }
2980
3047
 
2981
 
   session->nodeArrayLock = HGFS_LOCK_NEW("HgfsNodeArrayLock");
 
3048
   session->nodeArrayLock = MXUser_CreateExclLock("HgfsNodeArrayLock",
 
3049
                                                  RANK_hgfsNodeArrayLock);
2982
3050
   if (session->nodeArrayLock == NULL) {
2983
 
      HGFS_LOCK_DESTROY(session->fileIOLock);
 
3051
      MXUser_DestroyExclLock(session->fileIOLock);
2984
3052
      free(session);
2985
3053
      LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
2986
3054
 
2987
3055
      return FALSE;
2988
3056
   }
2989
3057
 
2990
 
   session->searchArrayLock = HGFS_LOCK_NEW("HgfsSearchArrayLock");
 
3058
   session->searchArrayLock = MXUser_CreateExclLock("HgfsSearchArrayLock",
 
3059
                                                    RANK_hgfsSearchArrayLock);
2991
3060
   if (session->searchArrayLock == NULL) {
2992
 
      HGFS_LOCK_DESTROY(session->fileIOLock);
2993
 
      HGFS_LOCK_DESTROY(session->nodeArrayLock);
 
3061
      MXUser_DestroyExclLock(session->fileIOLock);
 
3062
      MXUser_DestroyExclLock(session->nodeArrayLock);
2994
3063
      free(session);
2995
3064
      LOG(4, ("%s: Could not create search array sync mutex.\n", __FUNCTION__));
2996
3065
 
2997
3066
      return FALSE;
2998
3067
   }
2999
3068
 
 
3069
   session->sessionId = HgfsGenerateSessionId();
 
3070
   session->maxPacketSize = MAX_SERVER_PACKET_SIZE_V4;
3000
3071
   /*
3001
3072
    * Initialize the node handling components.
3002
3073
    */
3149
3220
   ASSERT(session->nodeArray);
3150
3221
   ASSERT(session->searchArray);
3151
3222
 
3152
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
3223
   MXUser_AcquireExclLock(session->nodeArrayLock);
3153
3224
 
3154
3225
   LOG(4, ("%s: exiting.\n", __FUNCTION__));
3155
3226
   /* Recycle all nodes that are still in use, then destroy the node pool. */
3167
3238
   free(session->nodeArray);
3168
3239
   session->nodeArray = NULL;
3169
3240
 
3170
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
3241
   MXUser_ReleaseExclLock(session->nodeArrayLock);
3171
3242
 
3172
3243
   /*
3173
3244
    * Recycle all searches that are still in use, then destroy the
3174
3245
    * search pool.
3175
3246
    */
3176
3247
 
3177
 
   HGFS_LOCK_ACQUIRE(session->searchArrayLock);
 
3248
   MXUser_AcquireExclLock(session->searchArrayLock);
3178
3249
 
3179
3250
   for (i = 0; i < session->numSearches; i++) {
3180
3251
      if (DblLnkLst_IsLinked(&session->searchArray[i].links)) {
3185
3256
   free(session->searchArray);
3186
3257
   session->searchArray = NULL;
3187
3258
 
3188
 
   HGFS_LOCK_RELEASE(session->searchArrayLock);
 
3259
   MXUser_ReleaseExclLock(session->searchArrayLock);
3189
3260
 
3190
3261
   /* Teardown the locks for the sessions and destroy itself. */
3191
 
   HGFS_LOCK_DESTROY(session->nodeArrayLock);
3192
 
   HGFS_LOCK_DESTROY(session->searchArrayLock);
3193
 
   HGFS_LOCK_DESTROY(session->fileIOLock);
 
3262
   MXUser_DestroyExclLock(session->nodeArrayLock);
 
3263
   MXUser_DestroyExclLock(session->searchArrayLock);
 
3264
   MXUser_DestroyExclLock(session->fileIOLock);
3194
3265
   free(session);
3195
3266
}
3196
3267
 
3267
3338
void
3268
3339
HgfsServer_ProcessPacket(char const *packetIn,   // IN: incoming packet
3269
3340
                         char *packetOut,        // OUT: outgoing packet
3270
 
                         size_t *packetLen,      // IN/OUT: packet length
3271
 
                         HgfsReceiveFlags flags) // IN: flags
 
3341
                         size_t *packetLen)     // IN/OUT: packet length
3272
3342
{
3273
3343
   HgfsPacket packet;
3274
3344
   ASSERT(packetIn);
3304
3374
   packet.metaPacketSize = *packetLen;
3305
3375
   packet.replyPacket = packetOut;
3306
3376
   packet.replyPacketSize = HGFS_LARGE_PACKET_MAX;
 
3377
   packet.supportsAsync = FALSE;
3307
3378
 
3308
3379
   HgfsServerSessionReceive(&packet,
3309
 
                            hgfsStaticSession.session,
3310
 
                            0);
 
3380
                            hgfsStaticSession.session);
3311
3381
 
3312
3382
   /*
3313
3383
    * At this point, all the HGFS ops send reply synchronously. So
3351
3421
   HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
3352
3422
   HSPU_PutMetaPacket(packet, session);
3353
3423
   HSPU_PutReplyPacket(packet, session);
 
3424
   HSPU_PutDataPacketBuf(packet, session);
3354
3425
}
3355
3426
 
3356
3427
 
3380
3451
   Bool result = FALSE;
3381
3452
 
3382
3453
   ASSERT(packet);
3383
 
   ASSERT(packetOut);
3384
3454
   ASSERT(session);
3385
3455
 
3386
3456
   if (session->state == HGFS_SESSION_STATE_OPEN) {
3398
3468
#endif
3399
3469
   }
3400
3470
 
3401
 
   HgfsServerSessionPut(session);
3402
 
 
3403
3471
   return result;
3404
3472
}
3405
3473
 
3407
3475
/*
3408
3476
 *-----------------------------------------------------------------------------
3409
3477
 *
3410
 
 * HgfsPackAndSendPacket --
3411
 
 *
3412
 
 *      Packs up the reply with id and status and sends the packet.
3413
 
 *
3414
 
 * Results:
3415
 
 *      TRUE on success, FALSE otherwise.
3416
 
 *
3417
 
 * Side effects:
3418
 
 *      None
3419
 
 *
3420
 
 *-----------------------------------------------------------------------------
3421
 
 */
3422
 
 
3423
 
Bool
3424
 
HgfsPackAndSendPacket(HgfsPacket *packet,         // IN/OUT: Hgfs Packet
3425
 
                      char *packetOut,            // IN: Output packet to send
3426
 
                      size_t packetOutLen,        // IN: Output packet size
3427
 
                      HgfsInternalStatus status,  // IN: status
3428
 
                      HgfsHandle id,              // IN: id of the request packet
3429
 
                      HgfsSessionInfo *session,   // IN: session info
3430
 
                      HgfsSendFlags flags)        // IN: flags how to send
3431
 
{
3432
 
   HgfsReply *reply = (HgfsReply *)packetOut;
3433
 
 
3434
 
   ASSERT(packet);
3435
 
   ASSERT(packetOut);
3436
 
   ASSERT(session);
3437
 
   ASSERT(packetOutLen <= HGFS_LARGE_PACKET_MAX);
3438
 
 
3439
 
   reply->id = id;
3440
 
   reply->status = HgfsConvertFromInternalStatus(status);
3441
 
 
3442
 
   return HgfsPacketSend(packet, packetOut, packetOutLen, session, flags);
3443
 
}
3444
 
 
3445
 
 
3446
 
/*
3447
 
 *-----------------------------------------------------------------------------
3448
 
 *
3449
3478
 * HgfsInvalidateSessionObjects --
3450
3479
 *
3451
3480
 *      Iterates over all nodes and searches, invalidating and removing those
3473
3502
   LOG(4, ("%s: Beginning\n", __FUNCTION__));
3474
3503
 
3475
3504
 
3476
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
3505
   MXUser_AcquireExclLock(session->nodeArrayLock);
3477
3506
 
3478
3507
   /*
3479
3508
    * Iterate over each node, skipping those that are unused. For each node,
3515
3544
      }
3516
3545
   }
3517
3546
 
3518
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
3547
   MXUser_ReleaseExclLock(session->nodeArrayLock);
3519
3548
 
3520
 
   HGFS_LOCK_ACQUIRE(session->searchArrayLock);
 
3549
   MXUser_AcquireExclLock(session->searchArrayLock);
3521
3550
 
3522
3551
   /*
3523
3552
    * Iterate over each search, skipping those that are on the free list. For
3554
3583
      }
3555
3584
   }
3556
3585
 
3557
 
   HGFS_LOCK_RELEASE(session->searchArrayLock);
 
3586
   MXUser_ReleaseExclLock(session->searchArrayLock);
3558
3587
 
3559
3588
   LOG(4, ("%s: Ending\n", __FUNCTION__));
3560
3589
}
4012
4041
   unsigned int i;
4013
4042
   HgfsSearch *search;
4014
4043
 
4015
 
   HGFS_LOCK_ACQUIRE(session->searchArrayLock);
 
4044
   MXUser_AcquireExclLock(session->searchArrayLock);
4016
4045
 
4017
4046
   search = HgfsSearchHandle2Search(searchHandle, session);
4018
4047
   if (search != NULL) {
4025
4054
      }
4026
4055
   }
4027
4056
 
4028
 
   HGFS_LOCK_RELEASE(session->searchArrayLock);
 
4057
   MXUser_ReleaseExclLock(session->searchArrayLock);
4029
4058
#endif
4030
4059
}
4031
4060
 
4235
4264
   ASSERT(handle);
4236
4265
   ASSERT(shareName);
4237
4266
 
4238
 
   HGFS_LOCK_ACQUIRE(session->searchArrayLock);
 
4267
   MXUser_AcquireExclLock(session->searchArrayLock);
4239
4268
 
4240
4269
   search = HgfsAddNewSearch(baseDir, DIRECTORY_SEARCH_TYPE_DIR, shareName,
4241
4270
                             rootDir, session);
4242
4271
   if (!search) {
4243
4272
      LOG(4, ("%s: failed to get new search\n", __FUNCTION__));
4244
 
      status = HGFS_INTERNAL_STATUS_ERROR;
 
4273
      status = HGFS_ERROR_INTERNAL;
4245
4274
      goto out;
4246
4275
   }
4247
4276
 
4250
4279
                                                 &configOptions);
4251
4280
   if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
4252
4281
      LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, shareName));
4253
 
      status = HGFS_INTERNAL_STATUS_ERROR;
 
4282
      status = HGFS_ERROR_INTERNAL;
4254
4283
      HgfsRemoveSearchInternal(search, session);
4255
4284
      goto out;
4256
4285
   }
4270
4299
   *handle = HgfsSearch2SearchHandle(search);
4271
4300
 
4272
4301
  out:
4273
 
   HGFS_LOCK_RELEASE(session->searchArrayLock);
 
4302
   MXUser_ReleaseExclLock(session->searchArrayLock);
4274
4303
 
4275
4304
   return status;
4276
4305
}
4313
4342
   ASSERT(cleanupName);
4314
4343
   ASSERT(handle);
4315
4344
 
4316
 
   HGFS_LOCK_ACQUIRE(session->searchArrayLock);
 
4345
   MXUser_AcquireExclLock(session->searchArrayLock);
4317
4346
 
4318
4347
   search = HgfsAddNewSearch("", type, "", "", session);
4319
4348
   if (!search) {
4320
4349
      LOG(4, ("%s: failed to get new search\n", __FUNCTION__));
4321
 
      status = HGFS_INTERNAL_STATUS_ERROR;
 
4350
      status = HGFS_ERROR_INTERNAL;
4322
4351
      goto out;
4323
4352
   }
4324
4353
 
4326
4355
   if (result < 0) {
4327
4356
      LOG(4, ("%s: couldn't get dents\n", __FUNCTION__));
4328
4357
      HgfsRemoveSearchInternal(search, session);
4329
 
      status = HGFS_INTERNAL_STATUS_ERROR;
 
4358
      status = HGFS_ERROR_INTERNAL;
4330
4359
      goto out;
4331
4360
   }
4332
4361
 
4334
4363
   *handle = HgfsSearch2SearchHandle(search);
4335
4364
 
4336
4365
  out:
4337
 
   HGFS_LOCK_RELEASE(session->searchArrayLock);
 
4366
   MXUser_ReleaseExclLock(session->searchArrayLock);
4338
4367
 
4339
4368
   return status;
4340
4369
}
4365
4394
{
4366
4395
   Bool removed = FALSE;
4367
4396
 
4368
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
4397
   MXUser_AcquireExclLock(session->nodeArrayLock);
4369
4398
   removed = HgfsRemoveFromCacheInternal(handle, session);
4370
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
4399
   MXUser_ReleaseExclLock(session->nodeArrayLock);
4371
4400
 
4372
4401
   return removed;
4373
4402
}
4396
4425
{
4397
4426
   Bool cached = FALSE;
4398
4427
 
4399
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
4428
   MXUser_AcquireExclLock(session->nodeArrayLock);
4400
4429
   cached = HgfsIsCachedInternal(handle, session);
4401
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
4430
   MXUser_ReleaseExclLock(session->nodeArrayLock);
4402
4431
 
4403
4432
   return cached;
4404
4433
}
4507
4536
{
4508
4537
   Bool added = FALSE;
4509
4538
 
4510
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
4539
   MXUser_AcquireExclLock(session->nodeArrayLock);
4511
4540
   added = HgfsAddToCacheInternal(handle, session);
4512
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
4541
   MXUser_ReleaseExclLock(session->nodeArrayLock);
4513
4542
 
4514
4543
   return added;
4515
4544
}
4573
4602
      sharedFolderOpen = TRUE;
4574
4603
   }
4575
4604
 
4576
 
   HGFS_LOCK_ACQUIRE(session->nodeArrayLock);
 
4605
   MXUser_AcquireExclLock(session->nodeArrayLock);
4577
4606
 
4578
4607
   node = HgfsAddNewFileNode(openInfo, localId, fileDesc, append, len,
4579
4608
                             openInfo->cpName, sharedFolderOpen, session);
4580
4609
 
4581
4610
   if (node == NULL) {
4582
4611
      LOG(4, ("%s: Failed to add new node.\n", __FUNCTION__));
4583
 
      HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
4612
      MXUser_ReleaseExclLock(session->nodeArrayLock);
4584
4613
 
4585
4614
      HgfsCloseFile(fileDesc, NULL);
4586
4615
      return FALSE;
4592
4621
      HgfsCloseFile(fileDesc, NULL);
4593
4622
 
4594
4623
      LOG(4, ("%s: Failed to add node to the cache.\n", __FUNCTION__));
4595
 
      HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
4624
      MXUser_ReleaseExclLock(session->nodeArrayLock);
4596
4625
 
4597
4626
      return FALSE;
4598
4627
   }
4599
4628
 
4600
 
   HGFS_LOCK_RELEASE(session->nodeArrayLock);
 
4629
   MXUser_ReleaseExclLock(session->nodeArrayLock);
4601
4630
 
4602
4631
   /* Only after everything is successful, save the handle in the open info. */
4603
4632
   openInfo->file = handle;
4609
4638
/*
4610
4639
 *-----------------------------------------------------------------------------
4611
4640
 *
4612
 
 * HgfsValidatePacket --
4613
 
 *
4614
 
 *    Validates that packet is not malformed. Checks consistency of various
4615
 
 *    fields and sizes.
4616
 
 *
4617
 
 * Results:
4618
 
 *    TRUE if the packet is correct.
4619
 
 *    FALSE if the packet is malformed.
4620
 
 *
4621
 
 * Side effects:
4622
 
 *    None
4623
 
 *
4624
 
 *-----------------------------------------------------------------------------
4625
 
 */
4626
 
 
4627
 
static Bool
4628
 
HgfsValidatePacket(char const *packetIn,        // IN: request packet
4629
 
                   size_t packetSize)           // IN: request packet size
4630
 
{
4631
 
   HgfsRequest *request = (HgfsRequest *)packetIn;
4632
 
   Bool result = TRUE;
4633
 
   if (packetSize < sizeof *request) {
4634
 
      return FALSE;
4635
 
   }
4636
 
   if (request->op < HGFS_OP_CREATE_SESSION_V4) {
4637
 
      result = packetSize >= sizeof *request;
4638
 
   } else {
4639
 
      HgfsHeader *header = (HgfsHeader *)packetIn;
4640
 
      ASSERT(packetSize >= header->packetSize);
4641
 
      ASSERT(header->packetSize >= header->headerSize);
4642
 
      result = packetSize >= offsetof(HgfsHeader, requestId) &&
4643
 
               header->headerSize >= offsetof(HgfsHeader, reserved) &&
4644
 
               header->packetSize >= header->headerSize &&
4645
 
               packetSize >= header->packetSize;
4646
 
   }
4647
 
   return result;
4648
 
}
4649
 
 
4650
 
 
4651
 
/*
4652
 
 *-----------------------------------------------------------------------------
4653
 
 *
4654
 
 * HgfsGetPayloadSize --
4655
 
 *
4656
 
 *    Returns size of the payload based on incoming packet and total
4657
 
 *    packet size.
4658
 
 *
4659
 
 * Results:
4660
 
 *    Size of the payload in bytes.
4661
 
 *
4662
 
 * Side effects:
4663
 
 *    None
4664
 
 *
4665
 
 *-----------------------------------------------------------------------------
4666
 
 */
4667
 
 
4668
 
size_t
4669
 
HgfsGetPayloadSize(char const *packetIn,        // IN: request packet
4670
 
                   size_t packetSize)           // IN: request packet size
4671
 
{
4672
 
   HgfsRequest *request = (HgfsRequest *)packetIn;
4673
 
   size_t result;
4674
 
   ASSERT(packetSize >= sizeof *request);
4675
 
   if (request->op < HGFS_OP_CREATE_SESSION_V4) {
4676
 
      result = packetSize - sizeof *request;
4677
 
   } else {
4678
 
      HgfsHeader *header = (HgfsHeader *)packetIn;
4679
 
      ASSERT(packetSize >= header->packetSize);
4680
 
      ASSERT(header->packetSize >= header->headerSize);
4681
 
      result = header->packetSize - header->headerSize;
4682
 
   }
4683
 
   return result;
4684
 
}
4685
 
 
4686
 
 
4687
 
/*
4688
 
 *-----------------------------------------------------------------------------
4689
 
 *
4690
 
 * HgfsParseRequest --
4691
 
 *
4692
 
 *    Returns requested operation and pointer to the payload based on
4693
 
 *    incoming packet and total packet size.
4694
 
 *
4695
 
 * Results:
4696
 
 *    TRUE if the packet has been successfully processed.
4697
 
 *    FALSE if the incoming request is malformed.
4698
 
 *
4699
 
 * Side effects:
4700
 
 *    None
4701
 
 *
4702
 
 *-----------------------------------------------------------------------------
4703
 
 */
4704
 
 
4705
 
Bool
4706
 
HgfsParseRequest(char const *packetIn,        // IN: request packet
4707
 
                 size_t packetSize,           // IN: request packet size
4708
 
                 void const **payload,        // OUT: payload
4709
 
                 size_t *payloadSize,         // OUT: payloadSize
4710
 
                 HgfsOp *op)                  // OUT: operation
4711
 
{
4712
 
   HgfsRequest *request = (HgfsRequest *)packetIn;
4713
 
   Bool result = FALSE;
4714
 
   ASSERT(packetSize >= sizeof *request);
4715
 
   *payload = NULL;
4716
 
   *payloadSize = 0;
4717
 
   if (request->op < HGFS_OP_OPEN_V3) {
4718
 
      /* Legacy requests do not have a separate header. */
4719
 
      *payload = packetIn;
4720
 
      *op = request->op;
4721
 
      *payloadSize = packetSize;
4722
 
      result = TRUE;
4723
 
   } else if (request->op < HGFS_OP_CREATE_SESSION_V4) {
4724
 
      /* V3 header. */
4725
 
      if (packetSize > sizeof *request) {
4726
 
         *payload = HGFS_REQ_GET_PAYLOAD_V3(packetIn);
4727
 
         *payloadSize = packetSize - ((char *)*payload - packetIn);
4728
 
      }
4729
 
      *op = request->op;
4730
 
      result = TRUE;
4731
 
   } else {
4732
 
      /* V4 header. */
4733
 
      if (request->op == HGFS_V4_LEGACY_OPCODE) {
4734
 
         HgfsHeader *header = (HgfsHeader *)packetIn;
4735
 
         if (packetSize >= header->packetSize &&
4736
 
            header->packetSize >= header->headerSize) {
4737
 
            *op = header->op;
4738
 
            result = TRUE;
4739
 
            if (header->packetSize > header->headerSize) {
4740
 
               *payload = packetIn + header->headerSize;
4741
 
               *payloadSize = header->packetSize - header->headerSize;
4742
 
            }
4743
 
         }
4744
 
      }
4745
 
   }
4746
 
   return result;
4747
 
}
4748
 
 
4749
 
 
4750
 
/*
4751
 
 *-----------------------------------------------------------------------------
4752
 
 *
4753
 
 * HgfsUnpackOpenPayloadV1 --
4754
 
 *
4755
 
 *    Unpack and validate payload for hgfs open request V1 to the HgfsFileOpenInfo
4756
 
 *    structure that is used to pass around open request information.
4757
 
 *
4758
 
 * Results:
4759
 
 *    TRUE on success.
4760
 
 *    FALSE on failure.
4761
 
 *
4762
 
 * Side effects:
4763
 
 *    None
4764
 
 *
4765
 
 *-----------------------------------------------------------------------------
4766
 
 */
4767
 
 
4768
 
Bool
4769
 
HgfsUnpackOpenPayloadV1(HgfsRequestOpen *requestV1, // IN: request payload
4770
 
                        size_t payloadSize,         // IN: request payload size
4771
 
                        HgfsFileOpenInfo *openInfo) // IN/OUT: open info struct
4772
 
{
4773
 
   size_t extra;
4774
 
 
4775
 
   /* Enforced by the dispatch function. */
4776
 
   if (payloadSize < sizeof *requestV1) {
4777
 
      return FALSE;
4778
 
   }
4779
 
 
4780
 
   extra = payloadSize - sizeof *requestV1;
4781
 
 
4782
 
   /*
4783
 
    * The request file name length is user-provided, so this test must be
4784
 
    * carefully written to prevent wraparounds.
4785
 
    */
4786
 
   if (requestV1->fileName.length > extra) {
4787
 
      /* The input packet is smaller than the request. */
4788
 
      return FALSE;
4789
 
   }
4790
 
 
4791
 
   /* For OpenV1 requests, we know exactly what fields we expect. */
4792
 
   openInfo->mask = HGFS_OPEN_VALID_MODE |
4793
 
                    HGFS_OPEN_VALID_FLAGS |
4794
 
                    HGFS_OPEN_VALID_OWNER_PERMS |
4795
 
                    HGFS_OPEN_VALID_FILE_NAME;
4796
 
   openInfo->mode = requestV1->mode;
4797
 
   openInfo->cpName = requestV1->fileName.name;
4798
 
   openInfo->cpNameSize = requestV1->fileName.length;
4799
 
   openInfo->flags = requestV1->flags;
4800
 
   openInfo->ownerPerms = requestV1->permissions;
4801
 
   return TRUE;
4802
 
}
4803
 
 
4804
 
 
4805
 
/*
4806
 
 *-----------------------------------------------------------------------------
4807
 
 *
4808
 
 * HgfsUnpackOpenPayloadV2 --
4809
 
 *
4810
 
 *    Unpack and validate payload for hgfs open request V2 to the HgfsFileOpenInfo
4811
 
 *    structure that is used to pass around open request information.
4812
 
 *
4813
 
 * Results:
4814
 
 *    TRUE on success.
4815
 
 *    FALSE on failure.
4816
 
 *
4817
 
 * Side effects:
4818
 
 *    None
4819
 
 *
4820
 
 *-----------------------------------------------------------------------------
4821
 
 */
4822
 
 
4823
 
Bool
4824
 
HgfsUnpackOpenPayloadV2(HgfsRequestOpenV2 *requestV2, // IN: request payload
4825
 
                        size_t payloadSize,           // IN: request payload size
4826
 
                        HgfsFileOpenInfo *openInfo)   // IN/OUT: open info struct
4827
 
{
4828
 
   size_t extra;
4829
 
 
4830
 
   /* Enforced by the dispatch function. */
4831
 
   if (payloadSize < sizeof *requestV2) {
4832
 
      return FALSE;
4833
 
   }
4834
 
 
4835
 
   extra = payloadSize - sizeof *requestV2;
4836
 
 
4837
 
   if (!(requestV2->mask & HGFS_OPEN_VALID_FILE_NAME)) {
4838
 
      /* We do not support open requests without a valid file name. */
4839
 
      return FALSE;
4840
 
   }
4841
 
 
4842
 
   /*
4843
 
    * The request file name length is user-provided, so this test must be
4844
 
    * carefully written to prevent wraparounds.
4845
 
    */
4846
 
   if (requestV2->fileName.length > extra) {
4847
 
      /* The input packet is smaller than the request. */
4848
 
      return FALSE;
4849
 
   }
4850
 
 
4851
 
   /*
4852
 
    * Copy all the fields into our carrier struct. Some will probably be
4853
 
    * garbage, but it's simpler to copy everything now and check the
4854
 
    * valid bits before reading later.
4855
 
    */
4856
 
 
4857
 
   openInfo->mask = requestV2->mask;
4858
 
   openInfo->mode = requestV2->mode;
4859
 
   openInfo->cpName = requestV2->fileName.name;
4860
 
   openInfo->cpNameSize = requestV2->fileName.length;
4861
 
   openInfo->flags = requestV2->flags;
4862
 
   openInfo->specialPerms = requestV2->specialPerms;
4863
 
   openInfo->ownerPerms = requestV2->ownerPerms;
4864
 
   openInfo->groupPerms = requestV2->groupPerms;
4865
 
   openInfo->otherPerms = requestV2->otherPerms;
4866
 
   openInfo->attr = requestV2->attr;
4867
 
   openInfo->allocationSize = requestV2->allocationSize;
4868
 
   openInfo->desiredAccess = requestV2->desiredAccess;
4869
 
   openInfo->shareAccess = requestV2->shareAccess;
4870
 
   openInfo->desiredLock = requestV2->desiredLock;
4871
 
   return TRUE;
4872
 
}
4873
 
 
4874
 
 
4875
 
/*
4876
 
 *-----------------------------------------------------------------------------
4877
 
 *
4878
 
 * HgfsUnpackOpenPayloadV3 --
4879
 
 *
4880
 
 *    Unpack and validate payload for hgfs open request V3 to the HgfsFileOpenInfo
4881
 
 *    structure that is used to pass around open request information.
4882
 
 *
4883
 
 * Results:
4884
 
 *    TRUE on success.
4885
 
 *    FALSE on failure.
4886
 
 *
4887
 
 * Side effects:
4888
 
 *    None
4889
 
 *
4890
 
 *-----------------------------------------------------------------------------
4891
 
 */
4892
 
 
4893
 
Bool
4894
 
HgfsUnpackOpenPayloadV3(HgfsRequestOpenV3 *requestV3, // IN: request payload
4895
 
                        size_t payloadSize,           // IN: request payload size
4896
 
                        HgfsFileOpenInfo *openInfo)   // IN/OUT: open info struct
4897
 
{
4898
 
   size_t extra;
4899
 
 
4900
 
   /* Enforced by the dispatch function. */
4901
 
   if (payloadSize < sizeof *requestV3) {
4902
 
      return FALSE;
4903
 
   }
4904
 
 
4905
 
   extra = payloadSize - sizeof *requestV3;
4906
 
 
4907
 
   if (!(requestV3->mask & HGFS_OPEN_VALID_FILE_NAME)) {
4908
 
      /* We do not support open requests without a valid file name. */
4909
 
      return FALSE;
4910
 
   }
4911
 
 
4912
 
   /*
4913
 
    * The request file name length is user-provided, so this test must be
4914
 
    * carefully written to prevent wraparounds.
4915
 
    */
4916
 
   if (requestV3->fileName.length > extra) {
4917
 
      /* The input packet is smaller than the request. */
4918
 
      return FALSE;
4919
 
   }
4920
 
 
4921
 
   /*
4922
 
    * Copy all the fields into our carrier struct. Some will probably be
4923
 
    * garbage, but it's simpler to copy everything now and check the
4924
 
    * valid bits before reading later.
4925
 
    */
4926
 
   openInfo->mask = requestV3->mask;
4927
 
   openInfo->mode = requestV3->mode;
4928
 
   openInfo->cpName = requestV3->fileName.name;
4929
 
   openInfo->cpNameSize = requestV3->fileName.length;
4930
 
   openInfo->caseFlags = requestV3->fileName.caseType;
4931
 
   openInfo->flags = requestV3->flags;
4932
 
   openInfo->specialPerms = requestV3->specialPerms;
4933
 
   openInfo->ownerPerms = requestV3->ownerPerms;
4934
 
   openInfo->groupPerms = requestV3->groupPerms;
4935
 
   openInfo->otherPerms = requestV3->otherPerms;
4936
 
   openInfo->attr = requestV3->attr;
4937
 
   openInfo->allocationSize = requestV3->allocationSize;
4938
 
   openInfo->desiredAccess = requestV3->desiredAccess;
4939
 
   openInfo->shareAccess = requestV3->shareAccess;
4940
 
   openInfo->desiredLock = requestV3->desiredLock;
4941
 
   return TRUE;
4942
 
}
4943
 
 
4944
 
 
4945
 
/*
4946
 
 *-----------------------------------------------------------------------------
4947
 
 *
4948
 
 * HgfsUnpackOpenRequest --
4949
 
 *
4950
 
 *    Unpack hgfs open request to the HgfsFileOpenInfo structure that is used
4951
 
 *    to pass around open request information.
4952
 
 *
4953
 
 * Results:
4954
 
 *    TRUE on success.
4955
 
 *    FALSE on failure.
4956
 
 *
4957
 
 * Side effects:
4958
 
 *    None
4959
 
 *
4960
 
 *-----------------------------------------------------------------------------
4961
 
 */
4962
 
 
4963
 
Bool
4964
 
HgfsUnpackOpenRequest(char const *packetIn,        // IN: request packet
4965
 
                      size_t packetSize,           // IN: request packet size
4966
 
                      HgfsFileOpenInfo *openInfo)  // IN/OUT: open info structure
4967
 
{
4968
 
   void const *payload;
4969
 
   size_t payloadSize;
4970
 
   HgfsOp op;
4971
 
 
4972
 
   ASSERT(packetIn);
4973
 
   ASSERT(openInfo);
4974
 
   
4975
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, &op)) {
4976
 
      return FALSE;
4977
 
   }
4978
 
 
4979
 
   openInfo->requestType = op;
4980
 
   openInfo->caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
4981
 
 
4982
 
   switch (op) {
4983
 
   case HGFS_OP_OPEN_V3: {
4984
 
         HgfsRequestOpenV3 *requestV3 = (HgfsRequestOpenV3 *)payload;
4985
 
         LOG(4, ("%s: HGFS_OP_OPEN_V3\n", __FUNCTION__));
4986
 
 
4987
 
         if (!HgfsUnpackOpenPayloadV3(requestV3, payloadSize, openInfo)) {
4988
 
            return FALSE;
4989
 
         }
4990
 
         break;
4991
 
      }
4992
 
   case HGFS_OP_OPEN_V2: {
4993
 
         HgfsRequestOpenV2 *requestV2 = (HgfsRequestOpenV2 *)payload;
4994
 
 
4995
 
         if (!HgfsUnpackOpenPayloadV2(requestV2, payloadSize, openInfo)) {
4996
 
            return FALSE;
4997
 
         }
4998
 
         break;
4999
 
      }
5000
 
   case HGFS_OP_OPEN: {
5001
 
         HgfsRequestOpen *requestV1 = (HgfsRequestOpen *)payload;
5002
 
 
5003
 
         if (!HgfsUnpackOpenPayloadV1(requestV1, payloadSize, openInfo)) {
5004
 
            return FALSE;
5005
 
         }
5006
 
         break;
5007
 
      }
5008
 
   default:
5009
 
      NOT_REACHED();
5010
 
      return FALSE;
5011
 
   }
5012
 
 
5013
 
   return TRUE;
5014
 
}
5015
 
 
5016
 
/*
5017
 
 *-----------------------------------------------------------------------------
5018
 
 *
5019
 
 * HgfsPackReplyHeaderV4 --
5020
 
 *
5021
 
 *    Pack hgfs header that corresponds an incoming packet.
5022
 
 *
5023
 
 * Results:
5024
 
 *    None.
5025
 
 *
5026
 
 * Side effects:
5027
 
 *    None
5028
 
 *
5029
 
 *-----------------------------------------------------------------------------
5030
 
 */
5031
 
 
5032
 
static void
5033
 
HgfsPackReplyHeaderV4(HgfsInternalStatus status,    // IN: reply status
5034
 
                      uint32 payloadSize,           // IN: size of the reply payload
5035
 
                      HgfsHeader const *packetIn,   // IN: original incoming packet
5036
 
                      HgfsHeader *header)           // OUT: outgoing packet header
5037
 
{
5038
 
   memset(header, 0, sizeof *header);
5039
 
   header->version = 1;
5040
 
   header->dummy = HGFS_V4_LEGACY_OPCODE;
5041
 
   header->packetSize = payloadSize + sizeof *header;
5042
 
   header->headerSize = sizeof *header;
5043
 
   header->requestId = packetIn->requestId;
5044
 
   header->op = packetIn->op;
5045
 
   header->status = HgfsConvertFromInternalStatus(status);
5046
 
   header->flags = 0;
5047
 
   header->information = status;
5048
 
   header->sessionId = packetIn->sessionId;
5049
 
}
5050
 
 
5051
 
 
5052
 
/*
5053
 
 *-----------------------------------------------------------------------------
5054
 
 *
5055
 
 * HgfsPackLegacyReplyHeader --
5056
 
 *
5057
 
 *    Pack pre-V4 reply header.
5058
 
 *
5059
 
 * Results:
5060
 
 *    None.
5061
 
 *
5062
 
 * Side effects:
5063
 
 *    None
5064
 
 *
5065
 
 *-----------------------------------------------------------------------------
5066
 
 */
5067
 
 
5068
 
void
5069
 
HgfsPackLegacyReplyHeader(HgfsInternalStatus status,    // IN: reply status
5070
 
                          HgfsHandle id,                // IN: original packet id
5071
 
                          HgfsReply *header)            // OUT: outgoing packet header
5072
 
{
5073
 
   memset(header, 0, sizeof *header);
5074
 
   header->status = HgfsConvertFromInternalStatus(status);
5075
 
   header->id = id;
5076
 
}
5077
 
 
5078
 
 
5079
 
/*
5080
 
 *-----------------------------------------------------------------------------
5081
 
 *
5082
 
 * HgfsPackOpenReplyV3 --
5083
 
 *
5084
 
 *    Pack hgfs open V3 reply payload to the HgfsReplyOpenV3 structure.
5085
 
 *
5086
 
 * Results:
5087
 
 *    None.
5088
 
 *
5089
 
 * Side effects:
5090
 
 *    None
5091
 
 *
5092
 
 *-----------------------------------------------------------------------------
5093
 
 */
5094
 
 
5095
 
static void
5096
 
HgfsPackOpenReplyV3(HgfsFileOpenInfo *openInfo,   // IN: open info struct
5097
 
                    HgfsReplyOpenV3 *reply)       // OUT: size of packet
5098
 
{
5099
 
   reply->file = openInfo->file;
5100
 
   reply->reserved = 0;
5101
 
   if (openInfo->mask & HGFS_OPEN_VALID_SERVER_LOCK) {
5102
 
      reply->acquiredLock = openInfo->acquiredLock;
5103
 
   } else {
5104
 
      reply->acquiredLock = HGFS_LOCK_NONE;
5105
 
   }
5106
 
}
5107
 
 
5108
 
 
5109
 
/*
5110
 
 *-----------------------------------------------------------------------------
5111
 
 *
5112
 
 * HgfsPackOpenV2Reply --
5113
 
 *
5114
 
 *    Pack hgfs open V2 reply payload to the HgfsReplyOpenV3 structure.
5115
 
 *
5116
 
 * Results:
5117
 
 *    None.
5118
 
 *
5119
 
 * Side effects:
5120
 
 *    None
5121
 
 *
5122
 
 *-----------------------------------------------------------------------------
5123
 
 */
5124
 
 
5125
 
static void
5126
 
HgfsPackOpenV2Reply(HgfsFileOpenInfo *openInfo,   // IN: open info struct
5127
 
                    HgfsReplyOpenV2 *reply)       // OUT: reply payload
5128
 
{
5129
 
   reply->file = openInfo->file;
5130
 
   if (openInfo->mask & HGFS_OPEN_VALID_SERVER_LOCK) {
5131
 
      reply->acquiredLock = openInfo->acquiredLock;
5132
 
   } else {
5133
 
      reply->acquiredLock = HGFS_LOCK_NONE;
5134
 
   }
5135
 
}
5136
 
 
5137
 
 
5138
 
/*
5139
 
 *-----------------------------------------------------------------------------
5140
 
 *
5141
 
 * HgfsPackOpenV1Reply --
5142
 
 *
5143
 
 *    Pack hgfs open V1 reply payload to the HgfsReplyOpenV3 structure.
5144
 
 *
5145
 
 * Results:
5146
 
 *    None.
5147
 
 *
5148
 
 * Side effects:
5149
 
 *    None
5150
 
 *
5151
 
 *-----------------------------------------------------------------------------
5152
 
 */
5153
 
 
5154
 
static void
5155
 
HgfsPackOpenV1Reply(HgfsFileOpenInfo *openInfo,   // IN: open info struct
5156
 
                    HgfsReplyOpen *reply)         // OUT: reply payload
5157
 
{
5158
 
   reply->file = openInfo->file;
5159
 
}
5160
 
 
5161
 
 
5162
 
/*
5163
 
 *-----------------------------------------------------------------------------
5164
 
 *
5165
4641
 * HgfsAllocInitReply --
5166
4642
 *
5167
 
 *    Allocates hgfs reply packet and initializes its header.
 
4643
 *    Allocates hgfs reply packet and calculates pointer to HGFS payload.
5168
4644
 *
5169
4645
 * Results:
5170
4646
 *    TRUE on success, FALSE on failure.
5177
4653
 
5178
4654
Bool
5179
4655
HgfsAllocInitReply(HgfsPacket *packet,           // IN/OUT: Hgfs Packet
5180
 
                   char const *packetIn,         // IN: incoming packet
 
4656
                   char const *packetHeader,     // IN: packet header
5181
4657
                   size_t payloadSize,           // IN: payload size
5182
 
                   HgfsInternalStatus status,    // IN: reply status
5183
 
                   char **packetOut,             // OUT: allocated reply
5184
4658
                   void **payload,               // OUT: pointer to the reply payload
5185
 
                   size_t *packetSize,           // OUT: size of the allocated packet
5186
4659
                   HgfsSessionInfo *session)     // IN: Session Info
5187
4660
{
5188
 
   HgfsRequest *request = (HgfsRequest *)packetIn;
 
4661
   HgfsRequest *request = (HgfsRequest *)packetHeader;
5189
4662
   size_t replyPacketSize;
5190
4663
   size_t headerSize = 0; /* Replies prior to V3 do not have a header. */
5191
 
   HgfsInternalStatus dummyStatus;
 
4664
   Bool result = FALSE;
 
4665
   char *reply;
5192
4666
 
5193
4667
   if (HGFS_V4_LEGACY_OPCODE == request->op) {
5194
4668
      headerSize = sizeof(HgfsHeader);
5196
4670
              request->op > HGFS_OP_RENAME_V2) {
5197
4671
      headerSize = sizeof(HgfsReply);
5198
4672
   }
5199
 
   replyPacketSize = *packetSize = headerSize + payloadSize;
5200
 
   *packetOut = HSPU_GetReplyPacket(packet, &replyPacketSize, session);
5201
 
   HGFS_REPLYPKT_CHECK(packetOut, *packetSize, replyPacketSize, dummyStatus, exit);
5202
 
 
5203
 
   *payload = *packetOut + headerSize;
5204
 
   if (HGFS_V4_LEGACY_OPCODE == request->op) {
5205
 
      HgfsPackReplyHeaderV4(status,
5206
 
                            payloadSize,
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);
5212
 
   }
5213
 
 
5214
 
   return TRUE;
5215
 
exit:
5216
 
   return FALSE;
5217
 
}
5218
 
 
5219
 
 
5220
 
/*
5221
 
 *-----------------------------------------------------------------------------
5222
 
 *
5223
 
 * HgfsPackOpenReply --
5224
 
 *
5225
 
 *    Pack hgfs open reply to the HgfsReplyOpen{V2} structure.
5226
 
 *
5227
 
 * Results:
5228
 
 *    Always TRUE.
5229
 
 *
5230
 
 * Side effects:
5231
 
 *    None
5232
 
 *
5233
 
 *-----------------------------------------------------------------------------
5234
 
 */
5235
 
 
5236
 
Bool
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
5244
 
{
5245
 
   Bool result;
5246
 
   ASSERT(packetIn);
5247
 
   ASSERT(openInfo);
5248
 
   ASSERT(packetSize);
5249
 
 
5250
 
   *packetOut = NULL;
5251
 
   *packetSize = 0;
5252
 
 
5253
 
   switch (openInfo->requestType) {
5254
 
   case HGFS_OP_OPEN_V3: {
5255
 
      HgfsReplyOpenV3 *reply;
5256
 
 
5257
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5258
 
                                 (void **)&reply, packetSize, session);
5259
 
      if (result == FALSE) {
5260
 
         goto error;
5261
 
      }
5262
 
      HgfsPackOpenReplyV3(openInfo, reply);
5263
 
      break;
5264
 
   }
5265
 
   case HGFS_OP_OPEN_V2: {
5266
 
      HgfsReplyOpenV2 *reply;
5267
 
 
5268
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5269
 
                                 (void **)&reply, packetSize, session);
5270
 
      if (result == FALSE) {
5271
 
         goto error;
5272
 
      }
5273
 
      HgfsPackOpenV2Reply(openInfo, reply);
5274
 
      break;
5275
 
   }
5276
 
   case HGFS_OP_OPEN: {
5277
 
      HgfsReplyOpen *reply;
5278
 
 
5279
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5280
 
                                 (void **)&reply, packetSize, session);
5281
 
      if (result == FALSE) {
5282
 
         goto error;
5283
 
      }
5284
 
      HgfsPackOpenV1Reply(openInfo, reply);
5285
 
      break;
5286
 
   }
5287
 
   default:
5288
 
      goto error;
5289
 
   }
5290
 
 
5291
 
   return TRUE;
5292
 
error:
5293
 
   return FALSE;
5294
 
}
5295
 
 
5296
 
 
5297
 
/*
5298
 
 *-----------------------------------------------------------------------------
5299
 
 *
5300
 
 * HgfsUnpackClosePayload --
5301
 
 *
5302
 
 *    Unpack hgfs close payload to get the handle which need to be closed.
5303
 
 *
5304
 
 * Results:
5305
 
 *    TRUE on success.
5306
 
 *    FALSE on failure.
5307
 
 *
5308
 
 * Side effects:
5309
 
 *    None
5310
 
 *
5311
 
 *-----------------------------------------------------------------------------
5312
 
 */
5313
 
 
5314
 
Bool
5315
 
HgfsUnpackClosePayload(HgfsRequestClose *request,   // IN: payload
5316
 
                       size_t payloadSize,          // IN: payload size
5317
 
                       HgfsHandle* file)            // OUT: HGFS handle to close
5318
 
{
5319
 
   LOG(4, ("%s: HGFS_OP_CLOSE\n", __FUNCTION__));
5320
 
   if (payloadSize >= sizeof *request) {
5321
 
      *file = request->file;
5322
 
      return TRUE;
5323
 
   }
5324
 
   return FALSE;
5325
 
}
5326
 
 
5327
 
 
5328
 
/*
5329
 
 *-----------------------------------------------------------------------------
5330
 
 *
5331
 
 * HgfsUnpackClosePayloadV3 --
5332
 
 *
5333
 
 *    Unpack hgfs close payload V3 to get the handle which need to be closed.
5334
 
 *
5335
 
 * Results:
5336
 
 *    TRUE on success.
5337
 
 *    FALSE on failure.
5338
 
 *
5339
 
 * Side effects:
5340
 
 *    None
5341
 
 *
5342
 
 *-----------------------------------------------------------------------------
5343
 
 */
5344
 
 
5345
 
Bool
5346
 
HgfsUnpackClosePayloadV3(HgfsRequestCloseV3 *requestV3, // IN: payload
5347
 
                         size_t payloadSize,            // IN: payload size
5348
 
                         HgfsHandle* file)              // OUT: HGFS handle to close
5349
 
{
5350
 
   LOG(4, ("%s: HGFS_OP_CLOSE_V3\n", __FUNCTION__));
5351
 
   if (payloadSize >= sizeof *requestV3) {
5352
 
      *file = requestV3->file;
5353
 
      return TRUE;
5354
 
   }
5355
 
   return FALSE;
5356
 
}
5357
 
 
5358
 
 
5359
 
/*
5360
 
 *-----------------------------------------------------------------------------
5361
 
 *
5362
 
 * HgfsUnpackCloseRequest --
5363
 
 *
5364
 
 *    Unpack hgfs close request to get the handle to close.
5365
 
 *
5366
 
 * Results:
5367
 
 *    TRUE on success.
5368
 
 *    FALSE on failure.
5369
 
 *
5370
 
 * Side effects:
5371
 
 *    None
5372
 
 *
5373
 
 *-----------------------------------------------------------------------------
5374
 
 */
5375
 
 
5376
 
Bool
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
5381
 
{
5382
 
   void const *payload;
5383
 
   size_t payloadSize;
5384
 
 
5385
 
   ASSERT(packetIn);
5386
 
 
5387
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
5388
 
      return FALSE;
5389
 
   }
5390
 
 
5391
 
   switch (*op) {
5392
 
   case HGFS_OP_CLOSE_V3: {
5393
 
         HgfsRequestCloseV3 *requestV3 = (HgfsRequestCloseV3 *)payload;
5394
 
 
5395
 
         if (!HgfsUnpackClosePayloadV3(requestV3, payloadSize, file)) {
5396
 
            return FALSE;
5397
 
         }
5398
 
         break;
5399
 
      }
5400
 
   case HGFS_OP_CLOSE: {
5401
 
         HgfsRequestClose *requestV1 = (HgfsRequestClose *)payload;
5402
 
 
5403
 
         if (!HgfsUnpackClosePayload(requestV1, payloadSize, file)) {
5404
 
            return FALSE;
5405
 
         }
5406
 
         break;
5407
 
      }
5408
 
   default:
5409
 
      NOT_REACHED();
5410
 
      return FALSE;
5411
 
   }
5412
 
 
5413
 
   return TRUE;
5414
 
}
5415
 
 
5416
 
 
5417
 
/*
5418
 
 *-----------------------------------------------------------------------------
5419
 
 *
5420
 
 * HgfsPackCloseReply --
5421
 
 *
5422
 
 *    Pack hgfs close reply to the HgfsReplyClose(V3) structure.
5423
 
 *
5424
 
 * Results:
5425
 
 *    TRUE on success, FALSE on failure
5426
 
 *
5427
 
 * Side effects:
5428
 
 *    None
5429
 
 *
5430
 
 *-----------------------------------------------------------------------------
5431
 
 */
5432
 
 
5433
 
Bool
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
5441
 
{
5442
 
   Bool result;
5443
 
   ASSERT(packetIn);
5444
 
   ASSERT(packetSize);
5445
 
 
5446
 
   *packetOut = NULL;
5447
 
   *packetSize = 0;
5448
 
 
5449
 
   switch (op) {
5450
 
   case HGFS_OP_CLOSE_V3: {
5451
 
      HgfsReplyCloseV3 *reply;
5452
 
 
5453
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5454
 
                                  (void **)&reply, packetSize, session);
5455
 
      break;
5456
 
   }
5457
 
   case HGFS_OP_CLOSE: {
5458
 
      HgfsReplyClose *reply;
5459
 
 
5460
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5461
 
                                  (void **)&reply, packetSize, session);
5462
 
      break;
5463
 
   }
5464
 
   default:
5465
 
      result = FALSE;
5466
 
      NOT_REACHED();
5467
 
   }
5468
 
 
5469
 
   return result;
5470
 
}
5471
 
 
5472
 
 
5473
 
/*
5474
 
 *-----------------------------------------------------------------------------
5475
 
 *
5476
 
 * HgfsUnpackSearchClosePayload --
5477
 
 *
5478
 
 *    Unpack hgfs search close payload to get the search handle which need to be closed.
5479
 
 *
5480
 
 * Results:
5481
 
 *    TRUE on success.
5482
 
 *    FALSE on failure.
5483
 
 *
5484
 
 * Side effects:
5485
 
 *    None
5486
 
 *
5487
 
 *-----------------------------------------------------------------------------
5488
 
 */
5489
 
 
5490
 
Bool
5491
 
HgfsUnpackSearchClosePayload(HgfsRequestSearchClose *request, // IN: payload
5492
 
                             size_t payloadSize,              // IN: payload size
5493
 
                             HgfsHandle* search)              // OUT: search to close
5494
 
{
5495
 
   LOG(4, ("%s: HGFS_OP_SEARCH_CLOSE\n", __FUNCTION__));
5496
 
   if (payloadSize >= sizeof *request) {
5497
 
      *search = request->search;
5498
 
      return TRUE;
5499
 
   }
5500
 
   return FALSE;
5501
 
}
5502
 
 
5503
 
 
5504
 
/*
5505
 
 *-----------------------------------------------------------------------------
5506
 
 *
5507
 
 * HgfsUnpackClosePayloadV3 --
5508
 
 *
5509
 
 *    Unpack hgfs search close payload V3 to get the search handle which need to
5510
 
 *    be closed.
5511
 
 *
5512
 
 * Results:
5513
 
 *    TRUE on success.
5514
 
 *    FALSE on failure.
5515
 
 *
5516
 
 * Side effects:
5517
 
 *    None
5518
 
 *
5519
 
 *-----------------------------------------------------------------------------
5520
 
 */
5521
 
 
5522
 
Bool
5523
 
HgfsUnpackSearchClosePayloadV3(HgfsRequestSearchCloseV3 *requestV3, // IN: payload
5524
 
                               size_t payloadSize,                  // IN: payload size
5525
 
                               HgfsHandle* search)                  // OUT: search
5526
 
{
5527
 
   LOG(4, ("%s: HGFS_OP_SEARCH_CLOSE_V3\n", __FUNCTION__));
5528
 
   if (payloadSize >= sizeof *requestV3) {
5529
 
      *search = requestV3->search;
5530
 
      return TRUE;
5531
 
   }
5532
 
   return FALSE;
5533
 
}
5534
 
 
5535
 
 
5536
 
/*
5537
 
 *-----------------------------------------------------------------------------
5538
 
 *
5539
 
 * HgfsUnpackSearchCloseRequest --
5540
 
 *
5541
 
 *    Unpack hgfs search close request to get the search handle.
5542
 
 *
5543
 
 * Results:
5544
 
 *    TRUE on success.
5545
 
 *    FALSE on failure.
5546
 
 *
5547
 
 * Side effects:
5548
 
 *    None
5549
 
 *
5550
 
 *-----------------------------------------------------------------------------
5551
 
 */
5552
 
 
5553
 
Bool
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
5558
 
{
5559
 
   void const *payload;
5560
 
   size_t payloadSize;
5561
 
 
5562
 
   ASSERT(packetIn);
5563
 
 
5564
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
5565
 
      return FALSE;
5566
 
   }
5567
 
 
5568
 
   switch (*op) {
5569
 
   case HGFS_OP_SEARCH_CLOSE_V3: {
5570
 
         HgfsRequestSearchCloseV3 *requestV3 = (HgfsRequestSearchCloseV3 *)payload;
5571
 
 
5572
 
         if (!HgfsUnpackSearchClosePayloadV3(requestV3, payloadSize, search)) {
5573
 
            return FALSE;
5574
 
         }
5575
 
         break;
5576
 
      }
5577
 
   case HGFS_OP_SEARCH_CLOSE: {
5578
 
         HgfsRequestSearchClose *requestV1 = (HgfsRequestSearchClose *)payload;
5579
 
 
5580
 
         if (!HgfsUnpackSearchClosePayload(requestV1, payloadSize, search)) {
5581
 
            return FALSE;
5582
 
         }
5583
 
         break;
5584
 
      }
5585
 
   default:
5586
 
      NOT_REACHED();
5587
 
      return FALSE;
5588
 
   }
5589
 
 
5590
 
   return TRUE;
5591
 
}
5592
 
 
5593
 
 
5594
 
/*
5595
 
 *-----------------------------------------------------------------------------
5596
 
 *
5597
 
 * HgfsPackSearchCloseReply --
5598
 
 *
5599
 
 *    Pack hgfs SearchClose reply into a HgfsReplySearchClose(V3) structure.
5600
 
 *
5601
 
 * Results:
5602
 
 *    TRUE on success, FALSE on failure.
5603
 
 *
5604
 
 * Side effects:
5605
 
 *    None
5606
 
 *
5607
 
 *-----------------------------------------------------------------------------
5608
 
 */
5609
 
 
5610
 
Bool
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
5618
 
{
5619
 
   Bool result;
5620
 
   ASSERT(packetIn);
5621
 
   ASSERT(packetSize);
5622
 
 
5623
 
   *packetOut = NULL;
5624
 
   *packetSize = 0;
5625
 
 
5626
 
   switch (op) {
5627
 
   case HGFS_OP_SEARCH_CLOSE_V3: {
5628
 
      HgfsReplyCloseV3 *reply;
5629
 
 
5630
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5631
 
                                  (void **)&reply, packetSize, session);
5632
 
      break;
5633
 
   }
5634
 
   case HGFS_OP_SEARCH_CLOSE: {
5635
 
      HgfsReplyClose *reply;
5636
 
 
5637
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
5638
 
                                  (void **)&reply, packetSize, session);
5639
 
      break;
5640
 
   }
5641
 
   default:
5642
 
      NOT_REACHED();
5643
 
      result = FALSE;
5644
 
   }
5645
 
 
5646
 
   return result;
5647
 
}
5648
 
 
5649
 
 
5650
 
/*
5651
 
 *-----------------------------------------------------------------------------
5652
 
 *
5653
 
 * HgfsUnpackFileName --
5654
 
 *
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.
5657
 
 *
5658
 
 * Results:
5659
 
 *    TRUE on success, FALSE on failure (buffer too small).
5660
 
 *
5661
 
 * Side effects:
5662
 
 *    None
5663
 
 *
5664
 
 *-----------------------------------------------------------------------------
5665
 
 */
5666
 
 
5667
 
Bool
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
5672
 
{
5673
 
   /*
5674
 
    * The request file name length is user-provided, so this test must be
5675
 
    * carefully written to prevent wraparounds.
5676
 
    */
5677
 
   if (name->length > maxNameSize) {
5678
 
      /* The input packet is smaller than the request. */
5679
 
      return FALSE;
5680
 
   }
5681
 
   *cpName = name->name;
5682
 
   *cpNameSize = name->length;
5683
 
   return TRUE;
5684
 
}
5685
 
 
5686
 
 
5687
 
/*
5688
 
 *-----------------------------------------------------------------------------
5689
 
 *
5690
 
 * HgfsUnpackFileNameV3 --
5691
 
 *
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.
5695
 
 *
5696
 
 * Results:
5697
 
 *    TRUE on success, FALSE on failure (buffer too small).
5698
 
 *
5699
 
 * Side effects:
5700
 
 *    None
5701
 
 *
5702
 
 *-----------------------------------------------------------------------------
5703
 
 */
5704
 
 
5705
 
Bool
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
5713
 
{
5714
 
   /*
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.
5717
 
    */
5718
 
   if (name->flags & HGFS_FILE_NAME_USE_FILE_DESC) {
5719
 
      *file = name->fid;
5720
 
      *cpName = NULL;
5721
 
      *cpNameSize = 0;
5722
 
      *caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
5723
 
      *useHandle = TRUE;
5724
 
   } else {
5725
 
      /*
5726
 
       * The request file name length is user-provided, so this test must be
5727
 
       * carefully written to prevent wraparounds.
5728
 
       */
5729
 
      if (name->length > maxNameSize) {
5730
 
         /* The input packet is smaller than the request */
5731
 
         return FALSE;
5732
 
      }
5733
 
      *file = HGFS_INVALID_HANDLE;
5734
 
      *cpName = name->name;
5735
 
      *cpNameSize = name->length;
5736
 
      *caseFlags = name->caseType;
5737
 
      *useHandle = FALSE;
5738
 
   }
5739
 
   return TRUE;
5740
 
}
5741
 
 
5742
 
 
5743
 
/*
5744
 
 *-----------------------------------------------------------------------------
5745
 
 *
5746
 
 * HgfsUnpackDeletePayloadV3 --
5747
 
 *
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.
5752
 
 *
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
5755
 
 *    both operations.
5756
 
 *
5757
 
 * Results:
5758
 
 *    TRUE on success.
5759
 
 *    FALSE on failure.
5760
 
 *
5761
 
 * Side effects:
5762
 
 *    None
5763
 
 *
5764
 
 *-----------------------------------------------------------------------------
5765
 
 */
5766
 
 
5767
 
Bool
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
5775
 
{
5776
 
   Bool result;
5777
 
   Bool useHandle;
5778
 
 
5779
 
   if (payloadSize < sizeof *requestV3) {
5780
 
      return FALSE;
5781
 
   }
5782
 
 
5783
 
   *hints = requestV3->hints;
5784
 
 
5785
 
   result = HgfsUnpackFileNameV3(&requestV3->fileName,
5786
 
                                 payloadSize - sizeof *requestV3,
5787
 
                                 &useHandle,
5788
 
                                 cpName,
5789
 
                                 cpNameSize,
5790
 
                                 file,
5791
 
                                 caseFlags);
5792
 
   if (useHandle) {
5793
 
      *hints |= HGFS_DELETE_HINT_USE_FILE_DESC;
5794
 
   }
5795
 
 
5796
 
   return result;
5797
 
}
5798
 
 
5799
 
 
5800
 
/*
5801
 
 *-----------------------------------------------------------------------------
5802
 
 *
5803
 
 * HgfsUnpackDeletePayloadV2 --
5804
 
 *
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.
5809
 
 *
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
5812
 
 *    both operations.
5813
 
 *
5814
 
 * Results:
5815
 
 *    TRUE on success.
5816
 
 *    FALSE on failure.
5817
 
 *
5818
 
 * Side effects:
5819
 
 *    None
5820
 
 *
5821
 
 *-----------------------------------------------------------------------------
5822
 
 */
5823
 
 
5824
 
Bool
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
5831
 
{
5832
 
   Bool result = TRUE;
5833
 
 
5834
 
   /* Enforced by the dispatch function. */
5835
 
   ASSERT(payloadSize >= sizeof *requestV2);
5836
 
 
5837
 
   *file = HGFS_INVALID_HANDLE;
5838
 
   *hints = requestV2->hints;
5839
 
 
5840
 
   /*
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.
5843
 
    */
5844
 
 
5845
 
   if (requestV2->hints & HGFS_DELETE_HINT_USE_FILE_DESC) {
5846
 
      *file = requestV2->file;
5847
 
      *cpName = NULL;
5848
 
      *cpNameSize = 0;
5849
 
   } else {
5850
 
      result = HgfsUnpackFileName(&requestV2->fileName,
5851
 
                                  payloadSize - sizeof *requestV2,
5852
 
                                  cpName,
5853
 
                                  cpNameSize);
5854
 
   }
5855
 
   return result;
5856
 
}
5857
 
 
5858
 
 
5859
 
/*
5860
 
 *-----------------------------------------------------------------------------
5861
 
 *
5862
 
 * HgfsUnpackDeletePayloadV1 --
5863
 
 *
5864
 
 *    Unpack hgfs delete request V1 payload and initialize a corresponding
5865
 
 *    file name to tell us which to delete.
5866
 
 *
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
5869
 
 *    both operations.
5870
 
 *
5871
 
 * Results:
5872
 
 *    TRUE on success.
5873
 
 *    FALSE on failure.
5874
 
 *
5875
 
 * Side effects:
5876
 
 *    None
5877
 
 *
5878
 
 *-----------------------------------------------------------------------------
5879
 
 */
5880
 
 
5881
 
Bool
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
5886
 
{
5887
 
   return HgfsUnpackFileName(&requestV1->fileName,
5888
 
                             payloadSize - sizeof *requestV1,
5889
 
                             cpName,
5890
 
                             cpNameSize);
5891
 
}
5892
 
 
5893
 
 
5894
 
/*
5895
 
 *-----------------------------------------------------------------------------
5896
 
 *
5897
 
 * HgfsUnpackDeleteRequest --
5898
 
 *
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.
5903
 
 *
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
5906
 
 *    both operations.
5907
 
 *
5908
 
 * Results:
5909
 
 *    TRUE on success.
5910
 
 *    FALSE on failure.
5911
 
 *
5912
 
 * Side effects:
5913
 
 *    None
5914
 
 *
5915
 
 *-----------------------------------------------------------------------------
5916
 
 */
5917
 
 
5918
 
Bool
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
5927
 
{
5928
 
   void const *payload;
5929
 
   size_t payloadSize;
5930
 
 
5931
 
   ASSERT(packetIn);
5932
 
   ASSERT(cpName);
5933
 
   ASSERT(cpNameSize);
5934
 
   ASSERT(file);
5935
 
   ASSERT(hints);
5936
 
   ASSERT(caseFlags);
5937
 
 
5938
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
5939
 
      return FALSE;
5940
 
   }
5941
 
 
5942
 
   *caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
5943
 
   *hints = 0;
5944
 
   *file = HGFS_INVALID_HANDLE;
5945
 
 
5946
 
   switch (*op) {
5947
 
   case HGFS_OP_DELETE_FILE_V3:
5948
 
   case HGFS_OP_DELETE_DIR_V3: {
5949
 
      HgfsRequestDeleteV3 *requestV3 = (HgfsRequestDeleteV3 *)payload;
5950
 
 
5951
 
      if (!HgfsUnpackDeletePayloadV3(requestV3,
5952
 
                                     payloadSize,
5953
 
                                     cpName,
5954
 
                                     cpNameSize,
5955
 
                                     hints,
5956
 
                                     file,
5957
 
                                     caseFlags)) {
5958
 
         return FALSE;
5959
 
      }
5960
 
      break;
5961
 
   }
5962
 
   case HGFS_OP_DELETE_FILE_V2:
5963
 
   case HGFS_OP_DELETE_DIR_V2: {
5964
 
      HgfsRequestDeleteV2 *requestV2 = (HgfsRequestDeleteV2 *)payload;
5965
 
 
5966
 
      if (!HgfsUnpackDeletePayloadV2(requestV2,
5967
 
                                     payloadSize,
5968
 
                                     cpName,
5969
 
                                     cpNameSize,
5970
 
                                     hints,
5971
 
                                     file)) {
5972
 
         return FALSE;
5973
 
      }
5974
 
      break;
5975
 
   }
5976
 
   case HGFS_OP_DELETE_FILE:
5977
 
   case HGFS_OP_DELETE_DIR: {
5978
 
      HgfsRequestDelete *requestV1 = (HgfsRequestDelete *)payload;
5979
 
 
5980
 
      if (!HgfsUnpackDeletePayloadV1(requestV1,
5981
 
                                     payloadSize,
5982
 
                                     cpName,
5983
 
                                     cpNameSize)) {
5984
 
         return FALSE;
5985
 
      }
5986
 
      break;
5987
 
   }
5988
 
   default:
5989
 
      NOT_REACHED();
5990
 
      return FALSE;
5991
 
   }
5992
 
 
5993
 
   return TRUE;
5994
 
}
5995
 
 
5996
 
 
5997
 
/*
5998
 
 *-----------------------------------------------------------------------------
5999
 
 *
6000
 
 * HgfsPackDeleteReply --
6001
 
 *
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.
6007
 
 *
6008
 
 * Results:
6009
 
 *    TRUE if valid op version reply filled, FALSE otherwise.
6010
 
 *
6011
 
 * Side effects:
6012
 
 *    None
6013
 
 *
6014
 
 *-----------------------------------------------------------------------------
6015
 
 */
6016
 
 
6017
 
Bool
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
6025
 
{
6026
 
   Bool result = TRUE;
6027
 
   ASSERT(packetIn);
6028
 
   ASSERT(packetSize);
6029
 
 
6030
 
   *packetOut = NULL;
6031
 
   *packetSize = 0;
6032
 
 
6033
 
   /* No reply payload, just header. */
6034
 
   switch (op) {
6035
 
   case HGFS_OP_DELETE_FILE_V3:
6036
 
   case HGFS_OP_DELETE_DIR_V3: {
6037
 
      HgfsReplyDeleteV3 *reply;
6038
 
 
6039
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
6040
 
                                  (void **)&reply, packetSize, session);
6041
 
      break;
6042
 
   }
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;
6048
 
 
6049
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
6050
 
                                  (void **)&reply, packetSize, session);
6051
 
      break;
6052
 
   }
6053
 
   default:
6054
 
      LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, op));
6055
 
      result = FALSE;
6056
 
      NOT_REACHED();
6057
 
      break;
6058
 
   }
6059
 
 
6060
 
   return result;
6061
 
}
6062
 
 
6063
 
 
6064
 
/*
6065
 
 *-----------------------------------------------------------------------------
6066
 
 *
6067
 
 * HgfsUnpackRenamePayloadV3 --
6068
 
 *
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.
6073
 
 *
6074
 
 * Results:
6075
 
 *    TRUE on success.
6076
 
 *    FALSE on failure.
6077
 
 *
6078
 
 * Side effects:
6079
 
 *    None
6080
 
 *
6081
 
 *-----------------------------------------------------------------------------
6082
 
 */
6083
 
 
6084
 
Bool
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
6096
 
{
6097
 
   size_t extra;
6098
 
   HgfsFileNameV3 *newName;
6099
 
   Bool useHandle;
6100
 
 
6101
 
   LOG(4, ("%s: HGFS_OP_RENAME_V3\n", __FUNCTION__));
6102
 
 
6103
 
   if (payloadSize < sizeof *requestV3) {
6104
 
      return FALSE;
6105
 
   }
6106
 
   extra = payloadSize - sizeof *requestV3;
6107
 
 
6108
 
   *hints = requestV3->hints;
6109
 
 
6110
 
   /*
6111
 
    * Get the old and new filenames from the request.
6112
 
    *
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
6118
 
    * new name.
6119
 
    */
6120
 
 
6121
 
   /*
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
6124
 
    * and the target.
6125
 
    */
6126
 
   if (!HgfsUnpackFileNameV3(&requestV3->oldName,
6127
 
                             extra,
6128
 
                             &useHandle,
6129
 
                             cpOldName,
6130
 
                             cpOldNameLen,
6131
 
                             srcFile,
6132
 
                             oldCaseFlags)) {
6133
 
      return FALSE;
6134
 
   }
6135
 
   if (useHandle) {
6136
 
      *hints |= HGFS_RENAME_HINT_USE_SRCFILE_DESC;
6137
 
      newName = &requestV3->newName;
6138
 
   } else {
6139
 
      newName = (HgfsFileNameV3 *)(requestV3->oldName.name + 1 + *cpOldNameLen);
6140
 
      extra -= *cpOldNameLen;
6141
 
   }
6142
 
   if (!HgfsUnpackFileNameV3(newName,
6143
 
                             extra,
6144
 
                             &useHandle,
6145
 
                             cpNewName,
6146
 
                             cpNewNameLen,
6147
 
                             targetFile,
6148
 
                             newCaseFlags)) {
6149
 
      return FALSE;
6150
 
   }
6151
 
   if (useHandle) {
6152
 
      *hints |= HGFS_RENAME_HINT_USE_TARGETFILE_DESC;
6153
 
   }
6154
 
 
6155
 
   return TRUE;
6156
 
}
6157
 
 
6158
 
 
6159
 
/*
6160
 
 *-----------------------------------------------------------------------------
6161
 
 *
6162
 
 * HgfsUnpackRenamePayloadV2 --
6163
 
 *
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.
6168
 
 *
6169
 
 * Results:
6170
 
 *    TRUE on success.
6171
 
 *    FALSE on failure.
6172
 
 *
6173
 
 * Side effects:
6174
 
 *    None
6175
 
 *
6176
 
 *-----------------------------------------------------------------------------
6177
 
 */
6178
 
 
6179
 
Bool
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
6189
 
{
6190
 
   HgfsFileName *newName;
6191
 
   size_t extra;
6192
 
 
6193
 
   /* Enforced by the dispatch function. */
6194
 
   if (payloadSize < sizeof *requestV2) {
6195
 
      return FALSE;
6196
 
   }
6197
 
   extra = payloadSize - sizeof *requestV2;
6198
 
 
6199
 
   *hints = requestV2->hints;
6200
 
 
6201
 
   /*
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
6204
 
    * and the target.
6205
 
    */
6206
 
 
6207
 
   if (*hints & HGFS_RENAME_HINT_USE_SRCFILE_DESC) {
6208
 
      *srcFile = requestV2->srcFile;
6209
 
      *cpOldName = NULL;
6210
 
      *cpOldNameLen = 0;
6211
 
   } else {
6212
 
      if (!HgfsUnpackFileName(&requestV2->oldName,
6213
 
                              extra,
6214
 
                              cpOldName,
6215
 
                              cpOldNameLen)) {
6216
 
         return FALSE;
6217
 
      }
6218
 
      extra -= *cpOldNameLen;
6219
 
   }
6220
 
 
6221
 
   if (*hints & HGFS_RENAME_HINT_USE_TARGETFILE_DESC) {
6222
 
      *targetFile = requestV2->targetFile;
6223
 
      *cpNewName = NULL;
6224
 
      *cpNewNameLen = 0;
6225
 
   } else {
6226
 
      newName = (HgfsFileName *)((char *)(&requestV2->oldName + 1)
6227
 
                                             + *cpOldNameLen);
6228
 
      if (!HgfsUnpackFileName(newName,
6229
 
                              extra,
6230
 
                              cpNewName,
6231
 
                              cpNewNameLen)) {
6232
 
         return FALSE;
6233
 
      }
6234
 
   }
6235
 
   return TRUE;
6236
 
}
6237
 
 
6238
 
 
6239
 
/*
6240
 
 *-----------------------------------------------------------------------------
6241
 
 *
6242
 
 * HgfsUnpackRenamePayloadV1 --
6243
 
 *
6244
 
 *    Unpack hgfs rename request V1 payload and initialize a corresponding
6245
 
 *    old and new file names.
6246
 
 *
6247
 
 * Results:
6248
 
 *    TRUE on success.
6249
 
 *    FALSE on failure.
6250
 
 *
6251
 
 * Side effects:
6252
 
 *    None
6253
 
 *
6254
 
 *-----------------------------------------------------------------------------
6255
 
 */
6256
 
 
6257
 
Bool
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
6264
 
{
6265
 
   HgfsFileName *newName;
6266
 
   uint32 extra;
6267
 
 
6268
 
   if (payloadSize < sizeof *requestV1) {
6269
 
      return FALSE;
6270
 
   }
6271
 
 
6272
 
   extra = payloadSize - sizeof *requestV1;
6273
 
 
6274
 
   if (!HgfsUnpackFileName(&requestV1->oldName,
6275
 
                           extra,
6276
 
                           cpOldName,
6277
 
                           cpOldNameLen)) {
6278
 
      return FALSE;
6279
 
   }
6280
 
 
6281
 
   extra -= requestV1->oldName.length;
6282
 
   newName = (HgfsFileName *)((char *)(&requestV1->oldName + 1)
6283
 
                              + requestV1->oldName.length);
6284
 
 
6285
 
   return HgfsUnpackFileName(newName, extra, cpNewName, cpNewNameLen);
6286
 
}
6287
 
 
6288
 
 
6289
 
/*
6290
 
 *-----------------------------------------------------------------------------
6291
 
 *
6292
 
 * HgfsUnpackRenameRequest --
6293
 
 *
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.
6298
 
 *
6299
 
 * Results:
6300
 
 *    TRUE on success.
6301
 
 *    FALSE on failure.
6302
 
 *
6303
 
 * Side effects:
6304
 
 *    None
6305
 
 *
6306
 
 *-----------------------------------------------------------------------------
6307
 
 */
6308
 
 
6309
 
Bool
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
6322
 
{
6323
 
   void const *payload;
6324
 
   size_t payloadSize;
6325
 
 
6326
 
   ASSERT(packetIn);
6327
 
   ASSERT(cpOldName);
6328
 
   ASSERT(cpOldNameLen);
6329
 
   ASSERT(cpNewName);
6330
 
   ASSERT(cpNewNameLen);
6331
 
   ASSERT(srcFile);
6332
 
   ASSERT(targetFile);
6333
 
   ASSERT(hints);
6334
 
   ASSERT(oldCaseFlags);
6335
 
   ASSERT(newCaseFlags);
6336
 
 
6337
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
6338
 
      return FALSE;
6339
 
   }
6340
 
 
6341
 
   /* Default values for legacy requests. */
6342
 
   *oldCaseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
6343
 
   *newCaseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
6344
 
   *hints = 0;
6345
 
 
6346
 
   switch (*op) {
6347
 
   case HGFS_OP_RENAME_V3:
6348
 
   {
6349
 
      HgfsRequestRenameV3 *requestV3 = (HgfsRequestRenameV3 *)payload;
6350
 
 
6351
 
      if (!HgfsUnpackRenamePayloadV3(requestV3,
6352
 
                                     payloadSize,
6353
 
                                     cpOldName,
6354
 
                                     cpOldNameLen,
6355
 
                                     cpNewName,
6356
 
                                     cpNewNameLen,
6357
 
                                     hints,
6358
 
                                     srcFile,
6359
 
                                     targetFile,
6360
 
                                     oldCaseFlags,
6361
 
                                     newCaseFlags)) {
6362
 
         return FALSE;
6363
 
      }
6364
 
      break;
6365
 
   }
6366
 
   case HGFS_OP_RENAME_V2:
6367
 
   {
6368
 
      HgfsRequestRenameV2 *requestV2 = (HgfsRequestRenameV2 *)payload;
6369
 
 
6370
 
      if (!HgfsUnpackRenamePayloadV2(requestV2,
6371
 
                                     payloadSize,
6372
 
                                     cpOldName,
6373
 
                                     cpOldNameLen,
6374
 
                                     cpNewName,
6375
 
                                     cpNewNameLen,
6376
 
                                     hints,
6377
 
                                     srcFile,
6378
 
                                     targetFile)) {
6379
 
         return FALSE;
6380
 
      }
6381
 
      break;
6382
 
   }
6383
 
 
6384
 
   case HGFS_OP_RENAME:
6385
 
   {
6386
 
      HgfsRequestRename *requestV1 = (HgfsRequestRename *)payload;
6387
 
 
6388
 
      if (!HgfsUnpackRenamePayloadV1(requestV1,
6389
 
                                     payloadSize,
6390
 
                                     cpOldName,
6391
 
                                     cpOldNameLen,
6392
 
                                     cpNewName,
6393
 
                                     cpNewNameLen)) {
6394
 
         return FALSE;
6395
 
      }
6396
 
      break;
6397
 
   }
6398
 
 
6399
 
   default:
6400
 
      return FALSE;
6401
 
   }
6402
 
 
6403
 
   return TRUE;
6404
 
}
6405
 
 
6406
 
 
6407
 
/*
6408
 
 *-----------------------------------------------------------------------------
6409
 
 *
6410
 
 * HgfsPackRenameReply --
6411
 
 *
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.
6417
 
 *
6418
 
 * Results:
6419
 
 *    TRUE if valid op and reply set, FALSE otherwise.
6420
 
 *
6421
 
 * Side effects:
6422
 
 *    None
6423
 
 *
6424
 
 *-----------------------------------------------------------------------------
6425
 
 */
6426
 
 
6427
 
Bool
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
6435
 
{
6436
 
   Bool result = TRUE;
6437
 
   ASSERT(packetIn);
6438
 
   ASSERT(packetSize);
6439
 
 
6440
 
   *packetOut = NULL;
6441
 
   *packetSize = 0;
6442
 
 
6443
 
   switch (op) {
6444
 
   case HGFS_OP_RENAME_V3: {
6445
 
      HgfsReplyRenameV3 *reply;
6446
 
 
6447
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
6448
 
                                  (void **)&reply, packetSize, session);
6449
 
      break;
6450
 
   }
6451
 
   case HGFS_OP_RENAME_V2:
6452
 
   case HGFS_OP_RENAME: {
6453
 
      HgfsReplyRename *reply;
6454
 
 
6455
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
6456
 
                                  (void **)&reply, packetSize, session);
6457
 
      break;
6458
 
   }
6459
 
   default:
6460
 
      LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, op));
6461
 
      result = FALSE;
6462
 
      NOT_REACHED();
6463
 
      break;
6464
 
   }
6465
 
 
6466
 
   return result;
6467
 
}
6468
 
 
6469
 
 
6470
 
/*
6471
 
 *-----------------------------------------------------------------------------
6472
 
 *
6473
 
 * HgfsUnpackGetattrPayloadV3 --
6474
 
 *
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.
6479
 
 *
6480
 
 * Results:
6481
 
 *    TRUE on success.
6482
 
 *    FALSE on failure.
6483
 
 *
6484
 
 * Side effects:
6485
 
 *    None
6486
 
 *
6487
 
 *-----------------------------------------------------------------------------
6488
 
 */
6489
 
 
6490
 
Bool
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
6498
 
{
6499
 
   Bool result;
6500
 
   Bool useHandle;
6501
 
 
6502
 
   if (payloadSize < sizeof *requestV3) {
6503
 
      return FALSE;
6504
 
   }
6505
 
 
6506
 
   *hints = requestV3->hints;
6507
 
 
6508
 
   result = HgfsUnpackFileNameV3(&requestV3->fileName,
6509
 
                                 payloadSize - sizeof *requestV3,
6510
 
                                 &useHandle,
6511
 
                                 cpName,
6512
 
                                 cpNameSize,
6513
 
                                 file,
6514
 
                                 caseFlags);
6515
 
   if (useHandle) {
6516
 
      *hints |= HGFS_ATTR_HINT_USE_FILE_DESC;
6517
 
   }
6518
 
 
6519
 
   return result;
6520
 
}
6521
 
 
6522
 
 
6523
 
/*
6524
 
 *-----------------------------------------------------------------------------
6525
 
 *
6526
 
 * HgfsUnpackGetattrPayloadV2 --
6527
 
 *
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.
6532
 
 *
6533
 
 * Results:
6534
 
 *    TRUE on success.
6535
 
 *    FALSE on failure.
6536
 
 *
6537
 
 * Side effects:
6538
 
 *    None
6539
 
 *
6540
 
 *-----------------------------------------------------------------------------
6541
 
 */
6542
 
 
6543
 
Bool
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
6550
 
{
6551
 
   Bool result = TRUE;
6552
 
 
6553
 
   if (payloadSize < sizeof *requestV2) {
6554
 
      return FALSE;
6555
 
   }
6556
 
 
6557
 
 
6558
 
   *file = HGFS_INVALID_HANDLE;
6559
 
   *hints = requestV2->hints;
6560
 
 
6561
 
   /*
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.
6564
 
    */
6565
 
 
6566
 
   if (requestV2->hints & HGFS_ATTR_HINT_USE_FILE_DESC) {
6567
 
      *file = requestV2->file;
6568
 
      *cpName = NULL;
6569
 
      *cpNameSize = 0;
6570
 
   } else {
6571
 
      result = HgfsUnpackFileName(&requestV2->fileName,
6572
 
                                  payloadSize - sizeof *requestV2,
6573
 
                                  cpName,
6574
 
                                  cpNameSize);
6575
 
   }
6576
 
   return result;
6577
 
}
6578
 
 
6579
 
 
6580
 
/*
6581
 
 *-----------------------------------------------------------------------------
6582
 
 *
6583
 
 * HgfsUnpackGetattrPayloadV1 --
6584
 
 *
6585
 
 *    Unpack hgfs getattr request V1 payload and initialize a corresponding
6586
 
 *    file name to tell us which to get attributes.
6587
 
 *
6588
 
 * Results:
6589
 
 *    TRUE on success.
6590
 
 *    FALSE on failure.
6591
 
 *
6592
 
 * Side effects:
6593
 
 *    None
6594
 
 *
6595
 
 *-----------------------------------------------------------------------------
6596
 
 */
6597
 
 
6598
 
Bool
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
6603
 
{
6604
 
   return HgfsUnpackFileName(&requestV1->fileName,
6605
 
                             payloadSize - sizeof *requestV1,
6606
 
                             cpName,
6607
 
                             cpNameSize);
6608
 
}
6609
 
 
6610
 
 
6611
 
/*
6612
 
 *-----------------------------------------------------------------------------
6613
 
 *
6614
 
 * HgfsPackAttrV2 --
6615
 
 *
6616
 
 *    Packs attr version 2 reply structure.
6617
 
 *
6618
 
 * Results:
6619
 
 *    None.
6620
 
 *
6621
 
 * Side effects:
6622
 
 *    None
6623
 
 *
6624
 
 *-----------------------------------------------------------------------------
6625
 
 */
6626
 
 
6627
 
void
6628
 
HgfsPackAttrV2(HgfsFileAttrInfo *attr,     // IN: attr stucture
6629
 
              HgfsAttrV2 *attr2)          // OUT: attr in payload
6630
 
{
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;
6649
 
}
6650
 
 
6651
 
 
6652
 
/*
6653
 
 *-----------------------------------------------------------------------------
6654
 
 *
6655
 
 * HgfsUnpackAttrV2 --
6656
 
 *
6657
 
 *    Unpacks attr version 2 reply structure.
6658
 
 *
6659
 
 * Results:
6660
 
 *    None.
6661
 
 *
6662
 
 * Side effects:
6663
 
 *    None
6664
 
 *
6665
 
 *-----------------------------------------------------------------------------
6666
 
 */
6667
 
 
6668
 
void
6669
 
HgfsUnpackAttrV2(HgfsAttrV2 *attr2,          // IN: attr in payload
6670
 
                HgfsFileAttrInfo *attr)     // OUT: attr stucture
6671
 
{
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;
6690
 
}
6691
 
 
6692
 
 
6693
 
/*
6694
 
 *-----------------------------------------------------------------------------
6695
 
 *
6696
 
 * HgfsInitFileAttr --
6697
 
 *
6698
 
 *    Initializes HgfsFileAttrInfo structure.
6699
 
 *
6700
 
 * Results:
6701
 
 *    None.
6702
 
 *
6703
 
 * Side effects:
6704
 
 *    None
6705
 
 *
6706
 
 *-----------------------------------------------------------------------------
6707
 
 */
6708
 
 
6709
 
void
6710
 
HgfsInitFileAttr(HgfsOp op,                // IN: request type
6711
 
                 HgfsFileAttrInfo *attr)   // OUT: attr stucture
6712
 
{
6713
 
   /* Initialize all fields with 0. */
6714
 
   memset(attr, 0, sizeof *attr);
6715
 
 
6716
 
   /* Explicitly initialize fields which need it. */
6717
 
   attr->requestType = op;
6718
 
   attr->mask = HGFS_ATTR_VALID_NONE;
6719
 
}
6720
 
 
6721
 
 
6722
 
/*
6723
 
 *-----------------------------------------------------------------------------
6724
 
 *
6725
 
 * HgfsPackGetattrReplyPayloadV3 --
6726
 
 *
6727
 
 *    Packs Getattr V3 reply payload.
6728
 
 *
6729
 
 * Results:
6730
 
 *    None.
6731
 
 *
6732
 
 * Side effects:
6733
 
 *    None
6734
 
 *
6735
 
 *-----------------------------------------------------------------------------
6736
 
 */
6737
 
 
6738
 
void
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
6743
 
{
6744
 
   LOG(4, ("%s: attr type: %u\n", __FUNCTION__, reply->attr.type));
6745
 
 
6746
 
   HgfsPackAttrV2(attr, &reply->attr);
6747
 
   reply->reserved = 0;
6748
 
 
6749
 
   if (utf8TargetName) {
6750
 
      memcpy(reply->symlinkTarget.name, utf8TargetName, utf8TargetNameLen);
6751
 
      CPNameLite_ConvertTo(reply->symlinkTarget.name, utf8TargetNameLen,
6752
 
                           DIRSEPC);
6753
 
   } else {
6754
 
      ASSERT(utf8TargetNameLen == 0);
6755
 
   }
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;
6761
 
}
6762
 
 
6763
 
 
6764
 
/*
6765
 
 *-----------------------------------------------------------------------------
6766
 
 *
6767
 
 * HgfsPackGetattrReplyPayloadV2 --
6768
 
 *
6769
 
 *    Packs rename reply payload V2 requests.
6770
 
 *
6771
 
 * Results:
6772
 
 *    None.
6773
 
 *
6774
 
 * Side effects:
6775
 
 *    None
6776
 
 *
6777
 
 *-----------------------------------------------------------------------------
6778
 
 */
6779
 
 
6780
 
void
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
6787
 
{
6788
 
   reply->header.status = HgfsConvertFromInternalStatus(status);
6789
 
   reply->header.id = id;
6790
 
 
6791
 
   HgfsPackAttrV2(attr, &reply->attr);
6792
 
 
6793
 
   if (utf8TargetName) {
6794
 
      memcpy(reply->symlinkTarget.name, utf8TargetName, utf8TargetNameLen);
6795
 
      CPNameLite_ConvertTo(reply->symlinkTarget.name, utf8TargetNameLen,
6796
 
                           DIRSEPC);
6797
 
   } else {
6798
 
      ASSERT(utf8TargetNameLen == 0);
6799
 
   }
6800
 
   reply->symlinkTarget.length = utf8TargetNameLen;
6801
 
   reply->symlinkTarget.name[utf8TargetNameLen] = '\0';
6802
 
}
6803
 
 
6804
 
 
6805
 
/*
6806
 
 *-----------------------------------------------------------------------------
6807
 
 *
6808
 
 * HgfsPackGetattrReplyPayloadV1 --
6809
 
 *
6810
 
 *    Packs rename reply payload for V1 requests.
6811
 
 *
6812
 
 * Results:
6813
 
 *    None.
6814
 
 *
6815
 
 * Side effects:
6816
 
 *    None
6817
 
 *
6818
 
 *-----------------------------------------------------------------------------
6819
 
 */
6820
 
 
6821
 
void
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
6826
 
{
6827
 
   reply->header.status = HgfsConvertFromInternalStatus(status);
6828
 
   reply->header.id = id;
6829
 
 
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;
6833
 
   } else {
6834
 
      reply->attr.type = attr->type;
6835
 
   }
6836
 
 
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;
6843
 
}
6844
 
 
6845
 
 
6846
 
/*
6847
 
 *-----------------------------------------------------------------------------
6848
 
 *
6849
 
 * HgfsValidateReplySize --
6850
 
 *
6851
 
 *    Verify if the size of a reply does not exceed maximum supported size.
6852
 
 *
6853
 
 * Results:
6854
 
 *    TRUE if the packet size is acceptable, FALSE otherwise.
6855
 
 *
6856
 
 * Side effects:
6857
 
 *    None
6858
 
 *
6859
 
 *-----------------------------------------------------------------------------
6860
 
 */
6861
 
 
6862
 
Bool
6863
 
HgfsValidateReplySize(char const *packetIn,
6864
 
                      HgfsOp op,
6865
 
                      size_t packetSize)
6866
 
{
6867
 
   HgfsRequest *request = (HgfsRequest *)packetIn;
6868
 
   /*
6869
 
    * XXX:
6870
 
    * At the moment assume that V4 protocol does not impose any restrictions
6871
 
    * on the packet size.
6872
 
    * May need to review later.
6873
 
    */
6874
 
   if (HGFS_V4_LEGACY_OPCODE == request->op) {
6875
 
      return TRUE;
6876
 
   }
6877
 
 
6878
 
   if (HGFS_OP_READ_V3 == op) {
6879
 
      return packetSize <= HGFS_LARGE_PACKET_MAX;
6880
 
   }
6881
 
 
6882
 
   return packetSize <= HGFS_PACKET_MAX;
6883
 
}
6884
 
 
6885
 
 
6886
 
/*
6887
 
 *-----------------------------------------------------------------------------
6888
 
 *
6889
 
 * HgfsUnpackGetattrRequest --
6890
 
 *
6891
 
 *    Unpack hgfs getattr request and initialize a corresponding
6892
 
 *    HgfsFileAttrInfo structure that is used to pass around getattr request
6893
 
 *    information.
6894
 
 *
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.
6899
 
 *
6900
 
 * Results:
6901
 
 *    TRUE on success.
6902
 
 *    FALSE on failure.
6903
 
 *
6904
 
 * Side effects:
6905
 
 *    None
6906
 
 *
6907
 
 *-----------------------------------------------------------------------------
6908
 
 */
6909
 
 
6910
 
Bool
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
6919
 
{
6920
 
   void const *payload;
6921
 
   size_t payloadSize;
6922
 
   HgfsOp op;
6923
 
 
6924
 
   ASSERT(packetIn);
6925
 
   ASSERT(attrInfo);
6926
 
   ASSERT(cpName);
6927
 
   ASSERT(cpNameSize);
6928
 
   ASSERT(file);
6929
 
   ASSERT(caseType);
6930
 
 
6931
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, &op)) {
6932
 
      return FALSE;
6933
 
   }
6934
 
 
6935
 
   HgfsInitFileAttr(op, attrInfo);
6936
 
 
6937
 
   /* Default values for legacy requests. */
6938
 
   *caseType = HGFS_FILE_NAME_DEFAULT_CASE;
6939
 
   *hints = 0;
6940
 
   *file = HGFS_INVALID_HANDLE;
6941
 
 
6942
 
   switch (op) {
6943
 
   case HGFS_OP_GETATTR_V3: {
6944
 
      HgfsRequestGetattrV3 *requestV3 = (HgfsRequestGetattrV3 *)payload;
6945
 
 
6946
 
      if (!HgfsUnpackGetattrPayloadV3(requestV3,
6947
 
                                      payloadSize,
6948
 
                                      cpName,
6949
 
                                      cpNameSize,
6950
 
                                      hints,
6951
 
                                      file,
6952
 
                                      caseType)) {
6953
 
         return FALSE;
6954
 
      }
6955
 
      LOG(4, ("%s: HGFS_OP_GETATTR_V3: %u\n", __FUNCTION__, *caseType));
6956
 
      break;
6957
 
   }
6958
 
 
6959
 
   case HGFS_OP_GETATTR_V2: {
6960
 
      HgfsRequestGetattrV2 *requestV2 = (HgfsRequestGetattrV2 *)payload;
6961
 
 
6962
 
      if (!HgfsUnpackGetattrPayloadV2(requestV2,
6963
 
                                      payloadSize,
6964
 
                                      cpName,
6965
 
                                      cpNameSize,
6966
 
                                      hints,
6967
 
                                      file)) {
6968
 
         return FALSE;
6969
 
      }
6970
 
      break;
6971
 
   }
6972
 
 
6973
 
   case HGFS_OP_GETATTR: {
6974
 
      HgfsRequestGetattr *requestV1 = (HgfsRequestGetattr *)payload;
6975
 
 
6976
 
      if (!HgfsUnpackGetattrPayloadV1(requestV1,payloadSize, cpName, cpNameSize)) {
6977
 
         return FALSE;
6978
 
      }
6979
 
      break;
6980
 
   }
6981
 
 
6982
 
   default:
6983
 
      return FALSE;
6984
 
   }
6985
 
 
6986
 
   return TRUE;
6987
 
}
6988
 
 
6989
 
 
6990
 
/*
6991
 
 *-----------------------------------------------------------------------------
6992
 
 *
6993
 
 * HgfsPackGetattrReply --
6994
 
 *
6995
 
 *    Pack hgfs getattr reply to the HgfsReplyGetattr structure.
6996
 
 *
6997
 
 * Results:
6998
 
 *    TRUE on success.
6999
 
 *    FALSE on failure.
7000
 
 *
7001
 
 * Side effects:
7002
 
 *    None
7003
 
 *
7004
 
 *-----------------------------------------------------------------------------
7005
 
 */
7006
 
 
7007
 
Bool
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
7017
 
{
7018
 
   Bool result;
7019
 
   ASSERT(packetIn);
7020
 
   ASSERT(attr);
7021
 
 
7022
 
   *packetOut = NULL;
7023
 
   *packetSize = 0;
7024
 
 
7025
 
   switch (attr->requestType) {
7026
 
   case HGFS_OP_GETATTR_V3: {
7027
 
      HgfsReplyGetattrV3 *reply;
7028
 
      uint32 payloadSize = sizeof *reply + utf8TargetNameLen;
7029
 
 
7030
 
      result = HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7031
 
                                  (void **)&reply, packetSize, session);
7032
 
      if (result == FALSE) {
7033
 
         goto error;
7034
 
      }
7035
 
 
7036
 
      if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7037
 
         free(reply);
7038
 
         goto error;
7039
 
      }
7040
 
      HgfsPackGetattrReplyPayloadV3(attr, utf8TargetName, utf8TargetNameLen, reply);
7041
 
      break;
7042
 
   }
7043
 
 
7044
 
   case HGFS_OP_GETATTR_V2: {
7045
 
      HgfsReplyGetattrV2 *reply;
7046
 
      HgfsRequest *request = (HgfsRequest *)packetIn;
7047
 
      uint32 payloadSize = sizeof *reply + utf8TargetNameLen;
7048
 
 
7049
 
      result = HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7050
 
                                  (void **)&reply, packetSize, session);
7051
 
      if (result == FALSE) {
7052
 
         goto error;
7053
 
      }
7054
 
 
7055
 
      if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7056
 
         free(reply);
7057
 
         goto error;
7058
 
      }
7059
 
      HgfsPackGetattrReplyPayloadV2(request->id,
7060
 
                                    status,
7061
 
                                    attr,
7062
 
                                    utf8TargetName,
7063
 
                                    utf8TargetNameLen,
7064
 
                                    reply);
7065
 
      break;
7066
 
   }
7067
 
 
7068
 
   case HGFS_OP_GETATTR: {
7069
 
      HgfsReplyGetattr *reply;
7070
 
      HgfsRequest *request = (HgfsRequest *)packetIn;
7071
 
 
7072
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
7073
 
                                  (void **)&reply, packetSize, session);
7074
 
      if (result == FALSE) {
7075
 
         goto error;
7076
 
      }
7077
 
 
7078
 
      HgfsPackGetattrReplyPayloadV1(request->id, status, attr, reply);
7079
 
      break;
7080
 
   }
7081
 
 
7082
 
   default:
7083
 
      LOG(4, ("%s: Invalid GetAttr op.\n", __FUNCTION__));
7084
 
      NOT_REACHED();
7085
 
      result =  FALSE;
7086
 
   }
7087
 
 
7088
 
error:
7089
 
   return result;
7090
 
}
7091
 
 
7092
 
 
7093
 
/*
7094
 
 *-----------------------------------------------------------------------------
7095
 
 *
7096
 
 * HgfsPackSearchReadReplyPayloadV3 --
7097
 
 *
7098
 
 *    Packs SearchRead V3 reply payload.
7099
 
 *
7100
 
 * Results:
7101
 
 *    None.
7102
 
 *
7103
 
 * Side effects:
7104
 
 *    None
7105
 
 *
7106
 
 *-----------------------------------------------------------------------------
7107
 
 */
7108
 
 
7109
 
void
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
7114
 
{
7115
 
   HgfsDirEntry *dirent = (HgfsDirEntry *)reply->payload;
7116
 
 
7117
 
   reply->count = 1;
7118
 
   reply->reserved = 0;
7119
 
 
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;
7125
 
 
7126
 
   if (utf8NameLen != 0) {
7127
 
      memcpy(dirent->fileName.name, utf8Name, utf8NameLen);
7128
 
      dirent->fileName.name[utf8NameLen] = 0;
7129
 
 
7130
 
      HgfsPackAttrV2(attr, &dirent->attr);
7131
 
   }
7132
 
}
7133
 
 
7134
 
 
7135
 
/*
7136
 
 *-----------------------------------------------------------------------------
7137
 
 *
7138
 
 * HgfsPackSearchReadReplyPayloadV2 --
7139
 
 *
7140
 
 *    Packs SearchRead V2 reply payload.
7141
 
 *
7142
 
 * Results:
7143
 
 *    None.
7144
 
 *
7145
 
 * Side effects:
7146
 
 *    None
7147
 
 *
7148
 
 *-----------------------------------------------------------------------------
7149
 
 */
7150
 
 
7151
 
void
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
7156
 
{
7157
 
   reply->fileName.length = (uint32)utf8NameLen;
7158
 
 
7159
 
   if (utf8NameLen != 0) {
7160
 
      memcpy(reply->fileName.name, utf8Name, utf8NameLen);
7161
 
      reply->fileName.name[utf8NameLen] = 0;
7162
 
      HgfsPackAttrV2(attr, &reply->attr);
7163
 
   }
7164
 
}
7165
 
 
7166
 
 
7167
 
/*
7168
 
 *-----------------------------------------------------------------------------
7169
 
 *
7170
 
 * HgfsPackSearchReadReplyPayloadV1 --
7171
 
 *
7172
 
 *    Packs SearchRead V1 reply payload.
7173
 
 *
7174
 
 * Results:
7175
 
 *    None.
7176
 
 *
7177
 
 * Side effects:
7178
 
 *    None
7179
 
 *
7180
 
 *-----------------------------------------------------------------------------
7181
 
 */
7182
 
 
7183
 
void
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
7188
 
{
7189
 
   reply->fileName.length = (uint32)utf8NameLen;
7190
 
 
7191
 
   if (utf8NameLen != 0) {
7192
 
      memcpy(reply->fileName.name, utf8Name, utf8NameLen);
7193
 
      reply->fileName.name[utf8NameLen] = 0;
7194
 
 
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;
7198
 
      } else {
7199
 
         reply->attr.type = attr->type;
7200
 
      }
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;
7207
 
   }
7208
 
}
7209
 
 
7210
 
 
7211
 
/*
7212
 
 *-----------------------------------------------------------------------------
7213
 
 *
7214
 
 * HgfsUnpackSearchReadRequest --
7215
 
 *
7216
 
 *    Unpack hgfs search read request and initialize a corresponding
7217
 
 *    HgfsFileAttrInfo structure that is used to pass around attribute
7218
 
 *    information.
7219
 
 *
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.
7224
 
 *
7225
 
 * Results:
7226
 
 *    Always TRUE.
7227
 
 *
7228
 
 * Side effects:
7229
 
 *    None
7230
 
 *
7231
 
 *-----------------------------------------------------------------------------
7232
 
 */
7233
 
 
7234
 
Bool
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
7240
 
{
7241
 
   void const *payload;
7242
 
   size_t payloadSize;
7243
 
   HgfsOp op;
7244
 
 
7245
 
   ASSERT(packetIn);
7246
 
   ASSERT(attr);
7247
 
   ASSERT(hgfsSearchHandle);
7248
 
   ASSERT(offset);
7249
 
 
7250
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, &op)) {
7251
 
      return FALSE;
7252
 
   }
7253
 
 
7254
 
   HgfsInitFileAttr(op, attr);
7255
 
 
7256
 
 
7257
 
   if (op == HGFS_OP_SEARCH_READ_V3) {
7258
 
      HgfsRequestSearchReadV3 *request = (HgfsRequestSearchReadV3 *)payload;
7259
 
 
7260
 
      /* Enforced by the dispatch function. */
7261
 
      ASSERT(payloadSize >= sizeof *request);
7262
 
 
7263
 
      *hgfsSearchHandle = request->search;
7264
 
      *offset = request->offset;
7265
 
 
7266
 
      LOG(4, ("%s: HGFS_OP_SEARCH_READ_V3\n", __FUNCTION__));
7267
 
   } else {
7268
 
      HgfsRequestSearchRead *request = (HgfsRequestSearchRead *)payload;
7269
 
 
7270
 
      /* Enforced by the dispatch function. */
7271
 
      ASSERT(payloadSize >= sizeof *request);
7272
 
 
7273
 
      *hgfsSearchHandle = request->search;
7274
 
      *offset = request->offset;
7275
 
   }
7276
 
 
7277
 
   return TRUE;
7278
 
}
7279
 
 
7280
 
 
7281
 
/*
7282
 
 *-----------------------------------------------------------------------------
7283
 
 *
7284
 
 * HgfsPackSearchReadReply --
7285
 
 *
7286
 
 *    Pack hgfs search read reply to the HgfsReplySearchRead{V2} structure.
7287
 
 *
7288
 
 * Results:
7289
 
 *    TRUE on success.
7290
 
 *    FALSE on failure.
7291
 
 *
7292
 
 * Side effects:
7293
 
 *    None
7294
 
 *
7295
 
 *-----------------------------------------------------------------------------
7296
 
 */
7297
 
 
7298
 
Bool
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
7308
 
{
7309
 
   Bool result = TRUE;
7310
 
   ASSERT(packetIn);
7311
 
 
7312
 
   *packetOut = NULL;
7313
 
   *packetSize = 0;
7314
 
 
7315
 
   switch (attr->requestType) {
7316
 
   case HGFS_OP_SEARCH_READ_V3: {
7317
 
      HgfsReplySearchReadV3 *reply;
7318
 
      uint32 payloadSize = sizeof *reply + utf8NameLen + sizeof(HgfsDirEntry);
7319
 
 
7320
 
      if (!HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7321
 
                                  (void **)&reply, packetSize, session)) {
7322
 
         result = FALSE;
7323
 
         goto error;
7324
 
      }
7325
 
 
7326
 
      if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7327
 
         free(reply);
7328
 
         result = FALSE;
7329
 
         goto error;
7330
 
      }
7331
 
      HgfsPackSearchReadReplyPayloadV3(attr, utf8Name, utf8NameLen, reply);
7332
 
      break;
7333
 
   }
7334
 
 
7335
 
   case HGFS_OP_SEARCH_READ_V2: {
7336
 
      HgfsReplySearchReadV2 *reply;
7337
 
      uint32 payloadSize = sizeof *reply + utf8NameLen;
7338
 
 
7339
 
      if (!HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7340
 
                                  (void **)&reply, packetSize, session)) {
7341
 
         result = FALSE;
7342
 
         goto error;
7343
 
      }
7344
 
 
7345
 
      if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7346
 
         free(reply);
7347
 
         result = FALSE;
7348
 
         goto error;
7349
 
      }
7350
 
      HgfsPackSearchReadReplyPayloadV2(attr,
7351
 
                                       utf8Name,
7352
 
                                       utf8NameLen,
7353
 
                                       reply);
7354
 
      break;
7355
 
   }
7356
 
 
7357
 
   case HGFS_OP_SEARCH_READ: {
7358
 
      HgfsReplySearchRead *reply;
7359
 
      uint32 payloadSize = sizeof *reply + utf8NameLen;
7360
 
 
7361
 
      if (!HgfsAllocInitReply(packet, packetIn, payloadSize, status, packetOut,
7362
 
                                  (void **)&reply, packetSize, session)) {
7363
 
         result = FALSE;
7364
 
         goto error;
7365
 
      }
7366
 
 
7367
 
      if (!HgfsValidateReplySize(packetIn, attr->requestType, *packetSize)) {
7368
 
         free(reply);
7369
 
         result = FALSE;
7370
 
         goto error;
7371
 
      }
7372
 
      HgfsPackSearchReadReplyPayloadV1(attr,
7373
 
                                       utf8Name,
7374
 
                                       utf8NameLen,
7375
 
                                       reply);
7376
 
      break;
7377
 
   }
7378
 
 
7379
 
   default: {
7380
 
      LOG(4, ("%s: Invalid SearchRead Op.", __FUNCTION__));
7381
 
      NOT_REACHED();
7382
 
      result = FALSE;
7383
 
   }
7384
 
   }
7385
 
 
7386
 
error:
7387
 
   return result;
7388
 
}
7389
 
 
7390
 
 
7391
 
/*
7392
 
 *-----------------------------------------------------------------------------
7393
 
 *
7394
 
 * HgfsUnpackSetattrPayloadV3 --
7395
 
 *
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.
7400
 
 *
7401
 
 * Results:
7402
 
 *    TRUE on success.
7403
 
 *    FALSE on failure.
7404
 
 *
7405
 
 * Side effects:
7406
 
 *    None
7407
 
 *
7408
 
 *-----------------------------------------------------------------------------
7409
 
 */
7410
 
 
7411
 
Bool
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
7420
 
{
7421
 
   Bool result;
7422
 
   Bool useHandle;
7423
 
 
7424
 
   if (payloadSize < sizeof *requestV3) {
7425
 
      return FALSE;
7426
 
   }
7427
 
 
7428
 
   *hints = requestV3->hints;
7429
 
 
7430
 
   HgfsUnpackAttrV2(&requestV3->attr, attr);
7431
 
 
7432
 
   result = HgfsUnpackFileNameV3(&requestV3->fileName,
7433
 
                                 payloadSize - sizeof *requestV3,
7434
 
                                 &useHandle,
7435
 
                                 cpName,
7436
 
                                 cpNameSize,
7437
 
                                 file,
7438
 
                                 caseFlags);
7439
 
   if (useHandle) {
7440
 
      *hints |= HGFS_ATTR_HINT_USE_FILE_DESC;
7441
 
   }
7442
 
 
7443
 
   LOG(4, ("%s: unpacking HGFS_OP_SETATTR_V3, %u\n", __FUNCTION__,
7444
 
       *caseFlags));
7445
 
   return result;
7446
 
}
7447
 
 
7448
 
 
7449
 
/*
7450
 
 *-----------------------------------------------------------------------------
7451
 
 *
7452
 
 * HgfsUnpackSetattrPayloadV2 --
7453
 
 *
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.
7458
 
 *
7459
 
 * Results:
7460
 
 *    TRUE on success.
7461
 
 *    FALSE on failure.
7462
 
 *
7463
 
 * Side effects:
7464
 
 *    None
7465
 
 *
7466
 
 *-----------------------------------------------------------------------------
7467
 
 */
7468
 
 
7469
 
Bool
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
7477
 
{
7478
 
   Bool result = TRUE;
7479
 
 
7480
 
   /* Enforced by the dispatch function. */
7481
 
   if (payloadSize < sizeof *requestV2) {
7482
 
      return FALSE;
7483
 
   }
7484
 
 
7485
 
   LOG(4, ("%s: unpacking HGFS_OP_SETATTR_V2\n", __FUNCTION__));
7486
 
 
7487
 
   *file = HGFS_INVALID_HANDLE;
7488
 
   *hints = requestV2->hints;
7489
 
 
7490
 
   HgfsUnpackAttrV2(&requestV2->attr, attr);
7491
 
 
7492
 
   if (requestV2->hints & HGFS_ATTR_HINT_USE_FILE_DESC) {
7493
 
      *file = requestV2->file;
7494
 
      *cpName = NULL;
7495
 
      *cpNameSize = 0;
7496
 
   } else {
7497
 
      result = HgfsUnpackFileName(&requestV2->fileName,
7498
 
                                  payloadSize - sizeof *requestV2,
7499
 
                                  cpName,
7500
 
                                  cpNameSize);
7501
 
   }
7502
 
   return result;
7503
 
}
7504
 
 
7505
 
 
7506
 
/*
7507
 
 *-----------------------------------------------------------------------------
7508
 
 *
7509
 
 * HgfsUnpackSetattrPayloadV1 --
7510
 
 *
7511
 
 *    Unpack hgfs setattr request V1 payload and initialize a corresponding
7512
 
 *    file name to tell us which to set attributes.
7513
 
 *
7514
 
 * Results:
7515
 
 *    TRUE on success.
7516
 
 *    FALSE on failure.
7517
 
 *
7518
 
 * Side effects:
7519
 
 *    None
7520
 
 *
7521
 
 *-----------------------------------------------------------------------------
7522
 
 */
7523
 
 
7524
 
Bool
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
7531
 
{
7532
 
   LOG(4, ("%s: unpacking HGFS_OP_SETATTR\n", __FUNCTION__));
7533
 
 
7534
 
   attr->mask = 0;
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;
7550
 
 
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,
7560
 
                             cpName,
7561
 
                             cpNameSize);
7562
 
}
7563
 
 
7564
 
 
7565
 
/*
7566
 
 *-----------------------------------------------------------------------------
7567
 
 *
7568
 
 * HgfsUnpackSetattrRequest --
7569
 
 *
7570
 
 *    Unpack hgfs setattr request and initialize a corresponding
7571
 
 *    HgfsFileAttrInfo structure that is used to pass around setattr request
7572
 
 *    information.
7573
 
 *
7574
 
 * Results:
7575
 
 *    TRUE on success.
7576
 
 *    FALSE on failure.
7577
 
 *
7578
 
 * Side effects:
7579
 
 *    None
7580
 
 *
7581
 
 *-----------------------------------------------------------------------------
7582
 
 */
7583
 
 
7584
 
Bool
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
7593
 
{
7594
 
   void const *payload;
7595
 
   size_t payloadSize;
7596
 
   HgfsOp op;
7597
 
 
7598
 
   ASSERT(packetIn);
7599
 
   ASSERT(attr);
7600
 
   ASSERT(cpName);
7601
 
   ASSERT(cpNameSize);
7602
 
   ASSERT(file);
7603
 
   ASSERT(caseType);
7604
 
 
7605
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, &op)) {
7606
 
      return FALSE;
7607
 
   }
7608
 
 
7609
 
   attr->requestType = op;
7610
 
 
7611
 
   /* Default values for legacy requests. */
7612
 
   *caseType = HGFS_FILE_NAME_DEFAULT_CASE;
7613
 
   *hints = 0;
7614
 
   *file = HGFS_INVALID_HANDLE;
7615
 
 
7616
 
   switch (op) {
7617
 
   case HGFS_OP_SETATTR_V3:
7618
 
      {
7619
 
         HgfsRequestSetattrV3 *requestV3 = (HgfsRequestSetattrV3 *)payload;
7620
 
         if (!HgfsUnpackSetattrPayloadV3(requestV3,
7621
 
                                         payloadSize,
7622
 
                                         attr,
7623
 
                                         cpName,
7624
 
                                         cpNameSize,
7625
 
                                         hints,
7626
 
                                         file,
7627
 
                                         caseType)) {
7628
 
            return FALSE;
7629
 
         }
7630
 
         break;
7631
 
      }
7632
 
 
7633
 
   case HGFS_OP_SETATTR_V2:
7634
 
      {
7635
 
         HgfsRequestSetattrV2 *requestV2 = (HgfsRequestSetattrV2 *)payload;
7636
 
         if (!HgfsUnpackSetattrPayloadV2(requestV2,
7637
 
                                         payloadSize,
7638
 
                                         attr,
7639
 
                                         cpName,
7640
 
                                         cpNameSize,
7641
 
                                         hints,
7642
 
                                         file)) {
7643
 
            return FALSE;
7644
 
         }
7645
 
         break;
7646
 
      }
7647
 
   case HGFS_OP_SETATTR:
7648
 
      {
7649
 
         HgfsRequestSetattr *requestV1 = (HgfsRequestSetattr *)payload;
7650
 
         if (!HgfsUnpackSetattrPayloadV1(requestV1,
7651
 
                                         payloadSize,
7652
 
                                         attr,
7653
 
                                         cpName,
7654
 
                                         cpNameSize,
7655
 
                                         hints)) {
7656
 
            return FALSE;
7657
 
         }
7658
 
         break;
7659
 
      }
7660
 
   default:
7661
 
      return FALSE;
7662
 
   }
7663
 
 
7664
 
   return TRUE;
7665
 
}
7666
 
 
7667
 
 
7668
 
/*
7669
 
 *-----------------------------------------------------------------------------
7670
 
 *
7671
 
 * HgfsPackSetattrReply --
7672
 
 *
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.
7678
 
 *
7679
 
 * Results:
7680
 
 *    TRUE if valid op and reply set, FALSE otherwise.
7681
 
 *
7682
 
 * Side effects:
7683
 
 *    None
7684
 
 *
7685
 
 *-----------------------------------------------------------------------------
7686
 
 */
7687
 
 
7688
 
Bool
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
7696
 
{
7697
 
   Bool result = TRUE;
7698
 
 
7699
 
   ASSERT(packetIn);
7700
 
 
7701
 
   *packetOut = NULL;
7702
 
   *packetSize = 0;
7703
 
 
7704
 
   switch (op) {
7705
 
   case HGFS_OP_SETATTR_V3: {
7706
 
      HgfsReplySetattrV3 *reply;
7707
 
 
7708
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
7709
 
                         (void **)&reply, packetSize, session);
7710
 
      break;
7711
 
   }
7712
 
   case HGFS_OP_SETATTR_V2:
7713
 
   case HGFS_OP_SETATTR: {
7714
 
      HgfsReplySetattr *reply;
7715
 
 
7716
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
7717
 
                         (void **)&reply, packetSize, session);
7718
 
      break;
7719
 
   }
7720
 
   default:
7721
 
      result = FALSE;
7722
 
      LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, op));
7723
 
      NOT_REACHED();
7724
 
      break;
7725
 
   }
7726
 
 
7727
 
   ASSERT(result);
7728
 
 
7729
 
   return result;
7730
 
}
7731
 
 
7732
 
 
7733
 
/*
7734
 
 *-----------------------------------------------------------------------------
7735
 
 *
7736
 
 * HgfsUnpackCreateDirPayloadV3 --
7737
 
 *
7738
 
 *    Unpack hgfs create directory request V3 payload and initialize a corresponding
7739
 
 *    file name to tell us which directory to create.
7740
 
 *
7741
 
 * Results:
7742
 
 *    TRUE on success.
7743
 
 *    FALSE on failure.
7744
 
 *
7745
 
 * Side effects:
7746
 
 *    None
7747
 
 *
7748
 
 *-----------------------------------------------------------------------------
7749
 
 */
7750
 
 
7751
 
Bool
7752
 
HgfsUnpackCreateDirPayloadV3(HgfsRequestCreateDirV3 *requestV3, // IN: request payload
7753
 
                             size_t payloadSize,                // IN: payload size
7754
 
                             HgfsCreateDirInfo *info)           // IN/OUT: info struct
7755
 
{
7756
 
   /*
7757
 
    * The request file name length is user-provided, so this test must be
7758
 
    * carefully written to prevent wraparounds.
7759
 
    */
7760
 
 
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. */
7765
 
      return FALSE;
7766
 
   }
7767
 
   if (!(requestV3->mask & HGFS_CREATE_DIR_VALID_FILE_NAME)) {
7768
 
      /* We do not support requests without a valid file name. */
7769
 
      return FALSE;
7770
 
   }
7771
 
 
7772
 
   /*
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.
7776
 
    */
7777
 
 
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;
7787
 
   return TRUE;
7788
 
}
7789
 
 
7790
 
 
7791
 
/*
7792
 
 *-----------------------------------------------------------------------------
7793
 
 *
7794
 
 * HgfsUnpackCreateDirPayloadV2 --
7795
 
 *
7796
 
 *    Unpack hgfs create directory request V2 payload and initialize a corresponding
7797
 
 *    file name to tell us which directory to create.
7798
 
 *
7799
 
 * Results:
7800
 
 *    TRUE on success.
7801
 
 *    FALSE on failure.
7802
 
 *
7803
 
 * Side effects:
7804
 
 *    None
7805
 
 *
7806
 
 *-----------------------------------------------------------------------------
7807
 
 */
7808
 
 
7809
 
Bool
7810
 
HgfsUnpackCreateDirPayloadV2(HgfsRequestCreateDirV2 *requestV2, // IN: request payload
7811
 
                             size_t payloadSize,                // IN: payload size
7812
 
                             HgfsCreateDirInfo *info)           // IN/OUT: info struct
7813
 
{
7814
 
   /*
7815
 
    * The request file name length is user-provided, so this test must be
7816
 
    * carefully written to prevent wraparounds.
7817
 
    */
7818
 
 
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. */
7823
 
      return FALSE;
7824
 
   }
7825
 
   if (!(requestV2->mask & HGFS_CREATE_DIR_VALID_FILE_NAME)) {
7826
 
      /* We do not support requests without a valid file name. */
7827
 
      return FALSE;
7828
 
   }
7829
 
 
7830
 
   /*
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.
7834
 
    */
7835
 
 
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;
7843
 
   info->fileAttr = 0;
7844
 
   return TRUE;
7845
 
}
7846
 
 
7847
 
 
7848
 
/*
7849
 
 *-----------------------------------------------------------------------------
7850
 
 *
7851
 
 * HgfsUnpackCreateDirPayloadV1 --
7852
 
 *
7853
 
 *    Unpack hgfs create directory request V1 payload and initialize a corresponding
7854
 
 *    file name to tell us which directory to create.
7855
 
 *
7856
 
 * Results:
7857
 
 *    TRUE on success.
7858
 
 *    FALSE on failure.
7859
 
 *
7860
 
 * Side effects:
7861
 
 *    None
7862
 
 *
7863
 
 *-----------------------------------------------------------------------------
7864
 
 */
7865
 
 
7866
 
Bool
7867
 
HgfsUnpackCreateDirPayloadV1(HgfsRequestCreateDir *requestV1, // IN: request payload
7868
 
                             size_t payloadSize,              // IN: payload size
7869
 
                             HgfsCreateDirInfo *info)         // IN/OUT: info struct
7870
 
{
7871
 
   /*
7872
 
    * The request file name length is user-provided, so this test must be
7873
 
    * carefully written to prevent wraparounds.
7874
 
    */
7875
 
 
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. */
7880
 
      return FALSE;
7881
 
   }
7882
 
 
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;
7888
 
   info->fileAttr = 0;
7889
 
   return TRUE;
7890
 
}
7891
 
 
7892
 
 
7893
 
/*
7894
 
 *-----------------------------------------------------------------------------
7895
 
 *
7896
 
 * HgfsUnpackCreateDirRequest --
7897
 
 *
7898
 
 *    Unpack hgfs CreateDir request and initialize a corresponding
7899
 
 *    HgfsCreateDirInfo structure that is used to pass around CreateDir request
7900
 
 *    information.
7901
 
 *
7902
 
 * Results:
7903
 
 *    TRUE on success.
7904
 
 *    FALSE on failure.
7905
 
 *
7906
 
 * Side effects:
7907
 
 *    None
7908
 
 *
7909
 
 *-----------------------------------------------------------------------------
7910
 
 */
7911
 
 
7912
 
Bool
7913
 
HgfsUnpackCreateDirRequest(char const *packetIn,    // IN: incoming packet
7914
 
                           size_t packetSize,       // IN: size of packet
7915
 
                           HgfsCreateDirInfo *info) // IN/OUT: info struct
7916
 
{
7917
 
   void const *payload;
7918
 
   size_t payloadSize;
7919
 
   HgfsOp op;
7920
 
 
7921
 
   ASSERT(packetIn);
7922
 
   ASSERT(info);
7923
 
 
7924
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, &op)) {
7925
 
      return FALSE;
7926
 
   }
7927
 
 
7928
 
   info->requestType = op;
7929
 
   /* Default value for legacy requests. */
7930
 
   info->caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
7931
 
 
7932
 
   switch (op) {
7933
 
   case HGFS_OP_CREATE_DIR_V3:
7934
 
      {
7935
 
         HgfsRequestCreateDirV3 *requestV3 = (HgfsRequestCreateDirV3 *)payload;
7936
 
         if (!HgfsUnpackCreateDirPayloadV3(requestV3,
7937
 
                                           payloadSize,
7938
 
                                           info)) {
7939
 
            return FALSE;
7940
 
         }
7941
 
         break;
7942
 
      }
7943
 
 
7944
 
   case HGFS_OP_CREATE_DIR_V2:
7945
 
      {
7946
 
         HgfsRequestCreateDirV2 *requestV2 = (HgfsRequestCreateDirV2 *)payload;
7947
 
         if (!HgfsUnpackCreateDirPayloadV2(requestV2,
7948
 
                                           payloadSize,
7949
 
                                           info)) {
7950
 
            return FALSE;
7951
 
         }
7952
 
         break;
7953
 
      }
7954
 
   case HGFS_OP_CREATE_DIR:
7955
 
      {
7956
 
         HgfsRequestCreateDir *requestV1 = (HgfsRequestCreateDir *)payload;
7957
 
         if (!HgfsUnpackCreateDirPayloadV1(requestV1,
7958
 
                                           payloadSize,
7959
 
                                           info)) {
7960
 
            return FALSE;
7961
 
         }
7962
 
         break;
7963
 
      }
7964
 
   default:
7965
 
      return FALSE;
7966
 
   }
7967
 
 
7968
 
   return TRUE;
7969
 
}
7970
 
 
7971
 
 
7972
 
/*
7973
 
 *-----------------------------------------------------------------------------
7974
 
 *
7975
 
 * HgfsPackCreateDirReply --
7976
 
 *
7977
 
 *    Pack hgfs CreateDir reply.
7978
 
 *
7979
 
 * Results:
7980
 
 *    TRUE if valid op and reply set, FALSE otherwise.
7981
 
 *
7982
 
 * Side effects:
7983
 
 *    None
7984
 
 *
7985
 
 *-----------------------------------------------------------------------------
7986
 
 */
7987
 
 
7988
 
Bool
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
7996
 
{
7997
 
   Bool result = TRUE;
7998
 
 
7999
 
   ASSERT(packetIn);
8000
 
 
8001
 
   *packetOut = NULL;
8002
 
   *packetSize = 0;
8003
 
 
8004
 
   switch (op) {
8005
 
   case HGFS_OP_CREATE_DIR_V3: {
8006
 
      HgfsReplyCreateDirV3 *reply;
8007
 
 
8008
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
8009
 
                         (void **)&reply, packetSize, session);
8010
 
      break;
8011
 
   }
8012
 
   case HGFS_OP_CREATE_DIR_V2: {
8013
 
      HgfsReplyCreateDirV2 *reply;
8014
 
 
8015
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
8016
 
                         (void **)&reply, packetSize, session);
8017
 
      break;
8018
 
   }
8019
 
   case HGFS_OP_CREATE_DIR: {
8020
 
      HgfsReplyCreateDir *reply;
8021
 
 
8022
 
      result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
8023
 
                         (void **)&reply, packetSize, session);
8024
 
      break;
8025
 
   }
8026
 
   default:
8027
 
      result = FALSE;
8028
 
      LOG(4, ("%s: invalid op code %d\n", __FUNCTION__, op));
8029
 
      NOT_REACHED();
8030
 
      break;
8031
 
   }
8032
 
 
8033
 
   return result;
8034
 
}
8035
 
 
8036
 
 
8037
 
/*
8038
 
 *-----------------------------------------------------------------------------
8039
 
 *
8040
 
 * HgfsUnpackWriteWin32StreamPayloadV3 --
8041
 
 *
8042
 
 *    Unpack hgfs write stream request V3 payload and initialize a corresponding
8043
 
 *    file name to tell us which directory to create.
8044
 
 *
8045
 
 * Results:
8046
 
 *    TRUE on success.
8047
 
 *    FALSE on failure.
8048
 
 *
8049
 
 * Side effects:
8050
 
 *    None
8051
 
 *
8052
 
 *-----------------------------------------------------------------------------
8053
 
 */
8054
 
 
8055
 
Bool
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:
8062
 
{
8063
 
   LOG(4, ("%s: HGFS_OP_WRITE_WIN32_STREAM_V3\n", __FUNCTION__));
8064
 
   if (payloadSize < sizeof *requestV3) {
8065
 
      return FALSE;
8066
 
   }
8067
 
 
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;
8073
 
      return TRUE;
8074
 
   }
8075
 
 
8076
 
   return FALSE;
8077
 
}
8078
 
 
8079
 
/*
8080
 
 *-----------------------------------------------------------------------------
8081
 
 *
8082
 
 * HgfsUnpackWriteWin32StreamRequest --
8083
 
 *
8084
 
 *    Unpack hgfs SendFileUsingReader request. Returns file to write to, data
8085
 
 *    and whether to restore the security stream.
8086
 
 *
8087
 
 * Results:
8088
 
 *    TRUE on success.
8089
 
 *    FALSE on failure.
8090
 
 *
8091
 
 * Side effects:
8092
 
 *    None
8093
 
 *
8094
 
 *-----------------------------------------------------------------------------
8095
 
 */
8096
 
 
8097
 
Bool
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.
8105
 
{
8106
 
   void const *payload;
8107
 
   size_t payloadSize;
8108
 
 
8109
 
   ASSERT(packetIn);
8110
 
   ASSERT(file);
8111
 
   ASSERT(data);
8112
 
   ASSERT(dataSize);
8113
 
   ASSERT(doSecurity);
8114
 
 
8115
 
   if (!HgfsParseRequest(packetIn, packetSize, &payload, &payloadSize, op)) {
8116
 
      return FALSE;
8117
 
   }
8118
 
 
8119
 
   if (*op != HGFS_OP_WRITE_WIN32_STREAM_V3) {
8120
 
      /* The only supported version for the moment is V3. */
8121
 
      NOT_REACHED();
8122
 
      return FALSE;
8123
 
   }
8124
 
 
8125
 
   return HgfsUnpackWriteWin32StreamPayloadV3((HgfsRequestWriteWin32StreamV3 *)payload,
8126
 
                                              payloadSize,
8127
 
                                              file,
8128
 
                                              data,
8129
 
                                              dataSize,
8130
 
                                              doSecurity);
8131
 
}
8132
 
 
8133
 
 
8134
 
/*
8135
 
 *-----------------------------------------------------------------------------
8136
 
 *
8137
 
 * HgfsPackWriteWin32StreamReply --
8138
 
 *
8139
 
 *    Pack hgfs SendFileUsingReader reply.
8140
 
 *    Returns the actual amount of data written in the reply.
8141
 
 *
8142
 
 * Results:
8143
 
 *    TRUE if valid op and reply set, FALSE otherwise.
8144
 
 *
8145
 
 * Side effects:
8146
 
 *    None
8147
 
 *
8148
 
 *-----------------------------------------------------------------------------
8149
 
 */
8150
 
 
8151
 
Bool
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
8160
 
{
8161
 
   HgfsReplyWriteWin32StreamV3 *reply;
8162
 
   Bool result;
8163
 
 
8164
 
   ASSERT(packetIn);
8165
 
 
8166
 
   *packetOut = NULL;
8167
 
   *packetSize = 0;
8168
 
 
8169
 
   if (op != HGFS_OP_WRITE_WIN32_STREAM_V3) {
8170
 
      NOT_REACHED();
8171
 
      return FALSE;
8172
 
   }
8173
 
 
8174
 
   result = HgfsAllocInitReply(packet, packetIn, sizeof *reply, status, packetOut,
8175
 
                              (void **)&reply, packetSize, session);
8176
 
   if (result != FALSE) {
8177
 
      reply->actualSize = actualSize;
8178
 
   }
8179
 
 
8180
 
   return result;
8181
 
}
8182
 
 
 
4673
   replyPacketSize = headerSize + payloadSize;
 
4674
   reply = HSPU_GetReplyPacket(packet, &replyPacketSize, session);
 
4675
 
 
4676
   if (reply && (replyPacketSize >= headerSize + payloadSize)) {
 
4677
      result = TRUE;
 
4678
      if (payloadSize > 0) {
 
4679
         *payload = reply + headerSize;
 
4680
      } else {
 
4681
         *payload = NULL;
 
4682
      }
 
4683
   }
 
4684
 
 
4685
   return result;
 
4686
}
 
4687
 
 
4688
 
 
4689
/*
 
4690
 *-----------------------------------------------------------------------------
 
4691
 *
 
4692
 * HgfsServerRead --
 
4693
 *
 
4694
 *    Handle a Read request.
 
4695
 *
 
4696
 * Results:
 
4697
 *    HGFS_ERROR_SUCCESS on success.
 
4698
 *    HGFS error code on failure.
 
4699
 *
 
4700
 * Side effects:
 
4701
 *    None
 
4702
 *
 
4703
 *-----------------------------------------------------------------------------
 
4704
 */
 
4705
 
 
4706
static void
 
4707
HgfsServerRead(HgfsInputParam *input)  // IN: Input params
 
4708
{
 
4709
   HgfsInternalStatus status;
 
4710
   HgfsHandle file;
 
4711
   uint64 offset;
 
4712
   uint32 requiredSize;
 
4713
   size_t replyPayloadSize = 0;
 
4714
 
 
4715
   HGFS_ASSERT_INPUT(input);
 
4716
 
 
4717
   if (!HgfsUnpackReadRequest(input->payload, input->payloadSize, input->op, &file,
 
4718
                              &offset, &requiredSize)) {
 
4719
      status = HGFS_ERROR_PROTOCOL;
 
4720
   } else {
 
4721
      switch(input->op) {
 
4722
      case HGFS_OP_READ_FAST_V4:
 
4723
      case HGFS_OP_READ_V3: {
 
4724
            HgfsReplyReadV3 *reply;
 
4725
            void *payload;
 
4726
            uint32 inlineDataSize =
 
4727
               (HGFS_OP_READ_FAST_V4 == input->op) ? 0 : requiredSize;
 
4728
 
 
4729
            if (!HgfsAllocInitReply(input->packet, input->metaPacket,
 
4730
                                    sizeof *reply + inlineDataSize, (void **)&reply,
 
4731
                                    input->session)) {
 
4732
               status = HGFS_ERROR_PROTOCOL;
 
4733
            } else {
 
4734
               if (inlineDataSize > 0) {
 
4735
                  payload = reply->payload;
 
4736
               } else {
 
4737
                  payload = HSPU_GetDataPacketBuf(input->packet, BUF_WRITEABLE,
 
4738
                                                  input->session);
 
4739
               }
 
4740
               if (payload) {
 
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);
 
4747
                  }
 
4748
               } else {
 
4749
                  status = HGFS_ERROR_PROTOCOL;
 
4750
               }
 
4751
            }
 
4752
            break;
 
4753
         }
 
4754
      case HGFS_OP_READ: {
 
4755
            HgfsReplyRead *reply;
 
4756
 
 
4757
            if (HgfsAllocInitReply(input->packet, input->metaPacket,
 
4758
                                   sizeof *reply + requiredSize, (void **)&reply,
 
4759
                                   input->session)) {
 
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;
 
4764
               }
 
4765
            } else {
 
4766
               status = HGFS_ERROR_PROTOCOL;
 
4767
            }
 
4768
            break;
 
4769
         }
 
4770
      default:
 
4771
         NOT_IMPLEMENTED();
 
4772
         status = HGFS_ERROR_PROTOCOL;
 
4773
      }
 
4774
   }
 
4775
 
 
4776
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
4777
}
 
4778
 
 
4779
 
 
4780
/*
 
4781
 *-----------------------------------------------------------------------------
 
4782
 *
 
4783
 * HgfsServerWrite --
 
4784
 *
 
4785
 *    Handle a Write request.
 
4786
 *
 
4787
 * Results:
 
4788
 *    None.
 
4789
 *
 
4790
 * Side effects:
 
4791
 *    None
 
4792
 *
 
4793
 *-----------------------------------------------------------------------------
 
4794
 */
 
4795
 
 
4796
static void
 
4797
HgfsServerWrite(HgfsInputParam *input)  // IN: Input params
 
4798
{
 
4799
   uint32 numberBytesToWrite;
 
4800
   HgfsInternalStatus status;
 
4801
   HgfsWriteFlags flags;
 
4802
   uint64 offset;
 
4803
   char *dataToWrite;
 
4804
   uint32 replyActualSize;
 
4805
   size_t replyPayloadSize = 0;
 
4806
   HgfsHandle file;
 
4807
 
 
4808
   HGFS_ASSERT_INPUT(input);
 
4809
 
 
4810
   if (HgfsUnpackWriteRequest(input, &file, &offset, &numberBytesToWrite,
 
4811
                              &flags, &dataToWrite)) {
 
4812
 
 
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;
 
4819
          }
 
4820
      }
 
4821
   } else {
 
4822
      status = HGFS_ERROR_PROTOCOL;
 
4823
   }
 
4824
 
 
4825
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
4826
}
 
4827
 
 
4828
 
 
4829
/*
 
4830
 *-----------------------------------------------------------------------------
 
4831
 *
 
4832
 * HgfsQueryVolume --
 
4833
 *
 
4834
 *    Performs actual work to get free space and capacity for a volume or
 
4835
 *    a group of volumes.
 
4836
 *
 
4837
 * Results:
 
4838
 *    Zero on success.
 
4839
 *    Non-zero on failure.
 
4840
 *
 
4841
 * Side effects:
 
4842
 *    None
 
4843
 *
 
4844
 *
 
4845
 *-----------------------------------------------------------------------------
 
4846
 */
 
4847
HgfsInternalStatus
 
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
 
4854
{
 
4855
   HgfsInternalStatus status = HGFS_ERROR_SUCCESS;
 
4856
   uint64 outFreeBytes;
 
4857
   uint64 outTotalBytes;
 
4858
   char *utf8Name = NULL;
 
4859
   size_t utf8NameLen;
 
4860
   HgfsNameStatus nameStatus;
 
4861
   Bool firstShare = TRUE;
 
4862
   HgfsShareInfo shareInfo;
 
4863
   HgfsHandle handle;
 
4864
   VolumeInfoType infoType;
 
4865
   DirectoryEntry *dent;
 
4866
   size_t failed = 0;
 
4867
   size_t shares = 0;
 
4868
   int offset = 0;
 
4869
   HgfsInternalStatus firstErr = HGFS_ERROR_SUCCESS;
 
4870
   Bool success;
 
4871
 
 
4872
   /* It is now safe to read the file name field. */
 
4873
   nameStatus = HgfsServerGetShareInfo(fileName,
 
4874
                                       fileNameLength,
 
4875
                                       caseFlags,
 
4876
                                       &shareInfo,
 
4877
                                       &utf8Name,
 
4878
                                       &utf8NameLen);
 
4879
 
 
4880
   switch (nameStatus) {
 
4881
   case HGFS_NAME_STATUS_INCOMPLETE_BASE:
 
4882
      /*
 
4883
       * This is the base of our namespace. Clients can request a
 
4884
       * QueryVolumeInfo on it, on individual shares, or on just about
 
4885
       * any pathname.
 
4886
       */
 
4887
 
 
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,
 
4893
                                          session,
 
4894
                                          &handle);
 
4895
      if (status != 0) {
 
4896
         return status;
 
4897
      }
 
4898
 
 
4899
      /*
 
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.
 
4902
       */
 
4903
      infoType = VOLUME_INFO_TYPE_MIN;
 
4904
#ifndef VMX86_TOOLS
 
4905
      {
 
4906
         char *volumeInfoType = Config_GetString("min",
 
4907
                                                 "tools.hgfs.volumeInfoType");
 
4908
         if (!Str_Strcasecmp(volumeInfoType, "max")) {
 
4909
            infoType = VOLUME_INFO_TYPE_MAX;
 
4910
         }
 
4911
         free(volumeInfoType);
 
4912
      }
 
4913
#endif
 
4914
 
 
4915
      /*
 
4916
       * Now go through all shares and get share paths on the server.
 
4917
       * Then retrieve space info for each share's volume.
 
4918
       */
 
4919
      offset = 0;
 
4920
      while ((dent = HgfsGetSearchResult(handle, session, offset,
 
4921
                                         TRUE)) != NULL) {
 
4922
         char const *sharePath;
 
4923
         size_t sharePathLen;
 
4924
         uint64 currentFreeBytes  = 0;
 
4925
         uint64 currentTotalBytes = 0;
 
4926
         size_t length;
 
4927
 
 
4928
         length = strlen(dent->d_name);
 
4929
 
 
4930
         /*
 
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.
 
4934
          */
 
4935
         if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {
 
4936
            LOG(4, ("%s: Skipping fake share %s\n", __FUNCTION__,
 
4937
                    dent->d_name));
 
4938
            free(dent);
 
4939
            continue;
 
4940
         }
 
4941
 
 
4942
         /*
 
4943
          * The above check ignores '.' and '..' so we do not include them in
 
4944
          * the share count here.
 
4945
          */
 
4946
         shares++;
 
4947
 
 
4948
         /*
 
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.
 
4954
          */
 
4955
 
 
4956
         nameStatus = HgfsServerPolicy_GetSharePath(dent->d_name, length,
 
4957
                                                    HGFS_OPEN_MODE_READ_ONLY,
 
4958
                                                    &sharePathLen,
 
4959
                                                    &sharePath);
 
4960
         free(dent);
 
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);
 
4965
            }
 
4966
            failed++;
 
4967
            continue;
 
4968
         }
 
4969
 
 
4970
         /*
 
4971
          * Pick the drive with amount of space available and return that
 
4972
          * according to different volume info type.
 
4973
          */
 
4974
 
 
4975
 
 
4976
         if (!HgfsServerStatFs(sharePath, sharePathLen,
 
4977
                               &currentFreeBytes, &currentTotalBytes)) {
 
4978
            LOG(4, ("%s: error getting volume information\n",
 
4979
                    __FUNCTION__));
 
4980
            if (0 == firstErr) {
 
4981
               firstErr = HGFS_ERROR_IO;
 
4982
            }
 
4983
            failed++;
 
4984
            continue;
 
4985
         }
 
4986
 
 
4987
         /*
 
4988
          * Pick the drive with amount of space available and return that
 
4989
          * according to different volume info type.
 
4990
          */
 
4991
         switch (infoType) {
 
4992
         case VOLUME_INFO_TYPE_MIN:
 
4993
            if ((outFreeBytes > currentFreeBytes) || firstShare) {
 
4994
               firstShare = FALSE;
 
4995
               outFreeBytes  = currentFreeBytes;
 
4996
               outTotalBytes = currentTotalBytes;
 
4997
            }
 
4998
            break;
 
4999
         case VOLUME_INFO_TYPE_MAX:
 
5000
            if ((outFreeBytes < currentFreeBytes)) {
 
5001
               outFreeBytes  = currentFreeBytes;
 
5002
               outTotalBytes = currentTotalBytes;
 
5003
            }
 
5004
            break;
 
5005
         default:
 
5006
            NOT_IMPLEMENTED();
 
5007
         }
 
5008
      }
 
5009
      if (!HgfsRemoveSearch(handle, session)) {
 
5010
         LOG(4, ("%s: could not close search on base\n", __FUNCTION__));
 
5011
      }
 
5012
      if (shares == failed) {
 
5013
         if (firstErr != 0) {
 
5014
            /*
 
5015
             * We failed to query any of the shares.  We return the error]
 
5016
             * from the first share failure.
 
5017
             */
 
5018
            status = firstErr;
 
5019
         }
 
5020
         /* No shares but no error, return zero for sizes and success. */
 
5021
      }
 
5022
      break;
 
5023
   case HGFS_NAME_STATUS_COMPLETE:
 
5024
      ASSERT(utf8Name);
 
5025
      LOG(4,("%s: querying path %s\n", __FUNCTION__, utf8Name));
 
5026
      success = HgfsServerStatFs(utf8Name, utf8NameLen,
 
5027
                                 &outFreeBytes, &outTotalBytes);
 
5028
      free(utf8Name);
 
5029
      if (!success) {
 
5030
         LOG(4, ("%s: error getting volume information\n", __FUNCTION__));
 
5031
         status = HGFS_ERROR_IO;
 
5032
      }
 
5033
      break;
 
5034
   default:
 
5035
      LOG(4,("%s: file access check failed\n", __FUNCTION__));
 
5036
      status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
5037
   }
 
5038
 
 
5039
   *freeBytes  = outFreeBytes;
 
5040
   *totalBytes = outTotalBytes;
 
5041
 
 
5042
   return status;
 
5043
}
 
5044
 
 
5045
 
 
5046
/*
 
5047
 *-----------------------------------------------------------------------------
 
5048
 *
 
5049
 * HgfsServerQueryVolume --
 
5050
 *
 
5051
 *    Handle a Query Volume request.
 
5052
 *
 
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.
 
5060
 *
 
5061
 * Results:
 
5062
 *    None.
 
5063
 *
 
5064
 * Side effects:
 
5065
 *    None
 
5066
 *
 
5067
 *-----------------------------------------------------------------------------
 
5068
 */
 
5069
 
 
5070
static void
 
5071
HgfsServerQueryVolume(HgfsInputParam *input)  // IN: Input params
 
5072
{
 
5073
   HgfsInternalStatus status;
 
5074
   size_t replyPayloadSize = 0;
 
5075
   HgfsHandle file;
 
5076
   char *fileName;
 
5077
   size_t fileNameLength;
 
5078
   uint32 caseFlags;
 
5079
   Bool useHandle;
 
5080
   uint64 freeBytes;
 
5081
   uint64 totalBytes;
 
5082
 
 
5083
   HGFS_ASSERT_INPUT(input);
 
5084
 
 
5085
   if (HgfsUnpackQueryVolumeRequest(input->payload, input->payloadSize, input->op,
 
5086
                                    &useHandle, &fileName,
 
5087
                                    &fileNameLength, &caseFlags, &file)) {
 
5088
      /*
 
5089
       * We don't yet support file handle for this operation.
 
5090
       * Clients should retry using the file name.
 
5091
       */
 
5092
      if (useHandle) {
 
5093
         LOG(4, ("%s: Doesn't support file handle.\n", __FUNCTION__));
 
5094
         status = HGFS_ERROR_INVALID_PARAMETER;
 
5095
      } else {
 
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;
 
5103
            }
 
5104
         }
 
5105
      }
 
5106
   } else {
 
5107
      status = HGFS_ERROR_PROTOCOL;
 
5108
   }
 
5109
 
 
5110
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
5111
}
 
5112
 
 
5113
 
 
5114
/*
 
5115
 *-----------------------------------------------------------------------------
 
5116
 *
 
5117
 * HgfsSymlinkCreate --
 
5118
 *
 
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.
 
5122
 *
 
5123
 * Results:
 
5124
 *    Zero on success.
 
5125
 *    Non-zero on failure.
 
5126
 *
 
5127
 * Side effects:
 
5128
 *    None
 
5129
 *
 
5130
 *-----------------------------------------------------------------------------
 
5131
 */
 
5132
 
 
5133
HgfsInternalStatus
 
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
 
5141
{
 
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];
 
5149
 
 
5150
   /*
 
5151
    * It is now safe to read the symlink file name and the
 
5152
    * "targetName" field
 
5153
    */
 
5154
 
 
5155
   nameStatus = HgfsServerGetShareInfo(srcFileName,
 
5156
                                       srcFileNameLength,
 
5157
                                       srcCaseFlags,
 
5158
                                       &shareInfo,
 
5159
                                       &localSymlinkName,
 
5160
                                       &localSymlinkNameLen);
 
5161
   if (nameStatus == HGFS_NAME_STATUS_COMPLETE) {
 
5162
      if (shareInfo.writePermissions ) {
 
5163
         /* Get the config options. */
 
5164
         nameStatus = HgfsServerPolicy_GetShareOptions(srcFileName, srcFileNameLength,
 
5165
                                                       &configOptions);
 
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;
 
5170
            }
 
5171
         } else {
 
5172
            LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, srcFileName));
 
5173
            status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
5174
         }
 
5175
      } else {
 
5176
         status = HgfsPlatformFileExists(localSymlinkName);
 
5177
         if (status != 0) {
 
5178
            if (status == HGFS_ERROR_FILE_NOT_FOUND) {
 
5179
               status = HGFS_ERROR_ACCESS_DENIED;
 
5180
            }
 
5181
         } else {
 
5182
            status = HGFS_ERROR_FILE_EXIST;
 
5183
         }
 
5184
         LOG(4, ("%s: failed access check, error %d\n", __FUNCTION__, status));
 
5185
      }
 
5186
   } else {
 
5187
      LOG(4, ("%s: symlink name access check failed\n", __FUNCTION__));
 
5188
      status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
5189
   }
 
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';
 
5195
 
 
5196
      status = HgfsPlatformSymlinkCreate(localSymlinkName, localTargetName);
 
5197
   }
 
5198
 
 
5199
   free(localSymlinkName);
 
5200
   return status;
 
5201
}
 
5202
 
 
5203
 
 
5204
/*
 
5205
 *-----------------------------------------------------------------------------
 
5206
 *
 
5207
 * HgfsServerSymlinkCreate --
 
5208
 *
 
5209
 *    Handle a SymlinkCreate request.
 
5210
 *
 
5211
 * Results:
 
5212
 *    None.
 
5213
 *
 
5214
 * Side effects:
 
5215
 *    None
 
5216
 *
 
5217
 *-----------------------------------------------------------------------------
 
5218
 */
 
5219
 
 
5220
static void
 
5221
HgfsServerSymlinkCreate(HgfsInputParam *input)  // IN: Input params
 
5222
{
 
5223
   HgfsInternalStatus status;
 
5224
   HgfsHandle srcFile;
 
5225
   char *srcFileName;
 
5226
   size_t srcFileNameLength;
 
5227
   uint32 srcCaseFlags;
 
5228
   Bool srcUseHandle;
 
5229
   HgfsHandle trgFile;
 
5230
   char *trgFileName;
 
5231
   size_t trgFileNameLength;
 
5232
   uint32 trgCaseFlags;
 
5233
   Bool trgUseHandle;
 
5234
   size_t replyPayloadSize = 0;
 
5235
 
 
5236
   HGFS_ASSERT_INPUT(input);
 
5237
 
 
5238
   if (HgfsUnpackSymlinkCreateRequest(input->payload, input->payloadSize, input->op,
 
5239
                                      &srcUseHandle, &srcFileName,
 
5240
                                      &srcFileNameLength, &srcCaseFlags, &srcFile,
 
5241
                                      &trgUseHandle, &trgFileName,
 
5242
                                      &trgFileNameLength, &trgCaseFlags, &trgFile)) {
 
5243
      /*
 
5244
       * We don't yet support file handle for this operation.
 
5245
       * Clients should retry using the file name.
 
5246
       */
 
5247
      if (srcUseHandle || trgUseHandle) {
 
5248
         LOG(4, ("%s: Doesn't support file handle.\n", __FUNCTION__));
 
5249
         status = HGFS_ERROR_INVALID_PARAMETER;
 
5250
      } else {
 
5251
         status = HgfsSymlinkCreate(input->session, srcFileName, srcFileNameLength,
 
5252
                                    srcCaseFlags, trgFileName, trgFileNameLength,
 
5253
                                    trgCaseFlags);
 
5254
         if (HGFS_ERROR_SUCCESS == status) {
 
5255
            if (!HgfsPackSymlinkCreateReply(input->packet, input->metaPacket, input->op,
 
5256
                                            &replyPayloadSize, input->session)) {
 
5257
               status = HGFS_ERROR_INTERNAL;
 
5258
            }
 
5259
         }
 
5260
      }
 
5261
   } else {
 
5262
      status = HGFS_ERROR_PROTOCOL;
 
5263
   }
 
5264
 
 
5265
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
5266
}
 
5267
 
 
5268
 
 
5269
/*
 
5270
 *-----------------------------------------------------------------------------
 
5271
 *
 
5272
 * HgfsServerSearchOpen --
 
5273
 *
 
5274
 *    Handle a search open request.
 
5275
 *
 
5276
 * Results:
 
5277
 *    None.
 
5278
 *
 
5279
 * Side effects:
 
5280
 *    None
 
5281
 *
 
5282
 *-----------------------------------------------------------------------------
 
5283
 */
 
5284
 
 
5285
static void
 
5286
HgfsServerSearchOpen(HgfsInputParam *input)  // IN: Input params
 
5287
{
 
5288
   HgfsInternalStatus status;
 
5289
   size_t replyPayloadSize = 0;
 
5290
   char *dirName;
 
5291
   uint32 dirNameLength;
 
5292
   uint32 caseFlags = HGFS_FILE_NAME_DEFAULT_CASE;
 
5293
   HgfsHandle search;
 
5294
   HgfsNameStatus nameStatus;
 
5295
   HgfsShareInfo shareInfo;
 
5296
   char *baseDir = NULL;
 
5297
   size_t baseDirLen;
 
5298
 
 
5299
   HGFS_ASSERT_INPUT(input);
 
5300
 
 
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;
 
5312
         }
 
5313
      }
 
5314
   } else {
 
5315
      status = HGFS_ERROR_PROTOCOL;
 
5316
   }
 
5317
 
 
5318
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
5319
}
 
5320
 
 
5321
 
 
5322
/*
 
5323
 *-----------------------------------------------------------------------------
 
5324
 *
 
5325
 * HgfsValidateRenameFile --
 
5326
 *
 
5327
 *    Validates if the file can can participate in rename process either as
 
5328
 *    as a source or as a target.
 
5329
 *
 
5330
 * Results:
 
5331
 *    HGFS_ERROR_SUCCESS if rename operation is allowed.
 
5332
 *    Appropriate error code otherwise.
 
5333
 *
 
5334
 * Side effects:
 
5335
 *    Allcates locaFileName which must be freed by the caller.
 
5336
 *
 
5337
 *-----------------------------------------------------------------------------
 
5338
 */
 
5339
 
 
5340
HgfsInternalStatus
 
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:
 
5351
{
 
5352
   HgfsInternalStatus status;
 
5353
   Bool sharedFolderOpen = FALSE;
 
5354
   HgfsServerLock serverLock = HGFS_LOCK_NONE;
 
5355
   HgfsNameStatus nameStatus;
 
5356
 
 
5357
 
 
5358
   if (useHandle) {
 
5359
      status = HgfsPlatformGetFd(fileHandle, session, FALSE, descr);
 
5360
 
 
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,
 
5366
                                          localNameLength)) {
 
5367
         /*
 
5368
          * HgfsPlatformRename requires valid source file name even when file handle
 
5369
          * is specified.
 
5370
          * Also the name will be required to update the nodes on a successful
 
5371
          * rename operation.
 
5372
          */
 
5373
        LOG(4, ("%s: could not get file name for fd %d\n", __FUNCTION__,
 
5374
                *descr));
 
5375
        status = HGFS_ERROR_INVALID_HANDLE;
 
5376
      } else if (HgfsHandleIsSharedFolderOpen(fileHandle, session, &sharedFolderOpen) &&
 
5377
                                              sharedFolderOpen) {
 
5378
         LOG(4, ("%s: Cannot rename shared folder\n", __FUNCTION__));
 
5379
         status = HGFS_ERROR_ACCESS_DENIED;
 
5380
      }
 
5381
   } else {
 
5382
      nameStatus = HgfsServerGetShareInfo(cpName,
 
5383
                                          cpNameLength,
 
5384
                                          caseFlags,
 
5385
                                          shareInfo,
 
5386
                                          localFileName,
 
5387
                                          localNameLength);
 
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;
 
5395
      } else {
 
5396
         status = HGFS_ERROR_SUCCESS;
 
5397
      }
 
5398
   }
 
5399
 
 
5400
   ASSERT(*localFileName != NULL || HGFS_ERROR_SUCCESS != status);
 
5401
 
 
5402
   if (HGFS_ERROR_SUCCESS == status) {
 
5403
      if (HgfsFileHasServerLock(*localFileName, session, &serverLock, descr)) {
 
5404
         /*
 
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
 
5410
          * an error.
 
5411
          */
 
5412
 
 
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;
 
5416
      }
 
5417
   }
 
5418
 
 
5419
   return status;
 
5420
}
 
5421
 
 
5422
 
 
5423
/*
 
5424
 *-----------------------------------------------------------------------------
 
5425
 *
 
5426
 * HgfsServerRename --
 
5427
 *
 
5428
 *    Handle a Rename request.
 
5429
 *
 
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.
 
5433
 *
 
5434
 * Results:
 
5435
 *    None.
 
5436
 *
 
5437
 * Side effects:
 
5438
 *    None
 
5439
 *
 
5440
 *-----------------------------------------------------------------------------
 
5441
 */
 
5442
 
 
5443
static void
 
5444
HgfsServerRename(HgfsInputParam *input)  // IN: Input params
 
5445
{
 
5446
   char *utf8OldName = NULL;
 
5447
   size_t utf8OldNameLen;
 
5448
   char *utf8NewName = NULL;
 
5449
   size_t utf8NewNameLen;
 
5450
   char *cpOldName;
 
5451
   size_t cpOldNameLen;
 
5452
   char *cpNewName;
 
5453
   size_t cpNewNameLen;
 
5454
   HgfsInternalStatus status;
 
5455
   fileDesc srcFileDesc;
 
5456
   fileDesc targetFileDesc;
 
5457
   HgfsHandle srcFile;
 
5458
   HgfsHandle targetFile;
 
5459
   HgfsRenameHint hints;
 
5460
   uint32 oldCaseFlags;
 
5461
   uint32 newCaseFlags;
 
5462
   HgfsShareInfo shareInfo;
 
5463
   size_t replyPayloadSize = 0;
 
5464
 
 
5465
   HGFS_ASSERT_INPUT(input);
 
5466
 
 
5467
   if (HgfsUnpackRenameRequest(input->payload, input->payloadSize, input->op, &cpOldName,
 
5468
                               &cpOldNameLen, &cpNewName, &cpNewNameLen,
 
5469
                               &hints, &srcFile, &targetFile, &oldCaseFlags,
 
5470
                               &newCaseFlags)) {
 
5471
      status = HgfsValidateRenameFile((hints & HGFS_RENAME_HINT_USE_SRCFILE_DESC) != 0,
 
5472
                                      srcFile,
 
5473
                                      cpOldName,
 
5474
                                      cpOldNameLen,
 
5475
                                      oldCaseFlags,
 
5476
                                      input->session,
 
5477
                                      &srcFileDesc,
 
5478
                                      &shareInfo,
 
5479
                                      &utf8OldName,
 
5480
                                      &utf8OldNameLen);
 
5481
      if (HGFS_ERROR_SUCCESS == status) {
 
5482
         /*
 
5483
          * Renaming a file requires both read and write permssions for the
 
5484
          * original file.
 
5485
          * However the error code must be different depending on the existence
 
5486
          * of the file with the same name.
 
5487
          */
 
5488
         if (!shareInfo.writePermissions || !shareInfo.readPermissions) {
 
5489
            status = HgfsPlatformFileExists(utf8OldName);
 
5490
            if (HGFS_ERROR_SUCCESS == status) {
 
5491
               status = HGFS_ERROR_ACCESS_DENIED;
 
5492
            }
 
5493
            LOG(4, ("HgfsServerRename: failed access check, error %d\n", status));
 
5494
         } else {
 
5495
            status =
 
5496
               HgfsValidateRenameFile((hints & HGFS_RENAME_HINT_USE_TARGETFILE_DESC) != 0,
 
5497
                                      targetFile,
 
5498
                                      cpNewName,
 
5499
                                      cpNewNameLen,
 
5500
                                      newCaseFlags,
 
5501
                                      input->session,
 
5502
                                      &targetFileDesc,
 
5503
                                      &shareInfo,
 
5504
                                      &utf8NewName,
 
5505
                                      &utf8NewNameLen);
 
5506
            if (HGFS_ERROR_SUCCESS == status) {
 
5507
               /*
 
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
 
5513
                * file exists.
 
5514
                */
 
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;
 
5520
                  }
 
5521
                  LOG(4, ("HgfsServerRename: failed access check, error %d\n", status));
 
5522
               }
 
5523
            }
 
5524
         }
 
5525
      }
 
5526
   } else {
 
5527
      status = HGFS_ERROR_PROTOCOL;
 
5528
   }
 
5529
 
 
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;
 
5540
         }
 
5541
      }
 
5542
   }
 
5543
 
 
5544
   free(utf8OldName);
 
5545
   free(utf8NewName);
 
5546
 
 
5547
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
5548
}
 
5549
 
 
5550
 
 
5551
/*
 
5552
 *-----------------------------------------------------------------------------
 
5553
 *
 
5554
 * HgfsServerCreateDir --
 
5555
 *
 
5556
 *    Handle a CreateDir request.
 
5557
 *
 
5558
 *    Simply converts to the local filename, calls platform specific
 
5559
 *    code to create a directory, and returns an appropriate response to the driver.
 
5560
 *
 
5561
 * Results:
 
5562
 *    None.
 
5563
 *
 
5564
 * Side effects:
 
5565
 *    None
 
5566
 *
 
5567
 *-----------------------------------------------------------------------------
 
5568
 */
 
5569
 
 
5570
static void
 
5571
HgfsServerCreateDir(HgfsInputParam *input)  // IN: Input params
 
5572
{
 
5573
   HgfsInternalStatus status;
 
5574
   HgfsNameStatus nameStatus;
 
5575
   HgfsCreateDirInfo info;
 
5576
   char *utf8Name;
 
5577
   size_t utf8NameLen;
 
5578
   size_t replyPayloadSize = 0;
 
5579
   HgfsShareInfo shareInfo;
 
5580
 
 
5581
   HGFS_ASSERT_INPUT(input);
 
5582
 
 
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) {
 
5588
         ASSERT(utf8Name);
 
5589
 
 
5590
         LOG(4, ("%s: making dir \"%s\"", __FUNCTION__, utf8Name));
 
5591
         /*
 
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.
 
5595
          */
 
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;
 
5602
               }
 
5603
            }
 
5604
         } else {
 
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;
 
5610
            }
 
5611
         }
 
5612
      } else {
 
5613
         /*
 
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.
 
5620
          */
 
5621
         if (nameStatus == HGFS_NAME_STATUS_DOES_NOT_EXIST) {
 
5622
             if (HgfsServerIsSharedFolderOnly(info.cpName,
 
5623
                                              info.cpNameSize)) {
 
5624
               nameStatus = HGFS_NAME_STATUS_ACCESS_DENIED;
 
5625
               LOG(4, ("%s: New file creation in share root not allowed\n", __FUNCTION__));
 
5626
            } else {
 
5627
               LOG(4, ("%s: Shared folder not found\n", __FUNCTION__));
 
5628
            }
 
5629
         } else {
 
5630
            LOG(4, ("%s: Shared folder access error %u\n", __FUNCTION__, nameStatus));
 
5631
         }
 
5632
 
 
5633
         status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
5634
      }
 
5635
 
 
5636
   } else {
 
5637
      status = HGFS_ERROR_PROTOCOL;
 
5638
   }
 
5639
 
 
5640
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
5641
}
 
5642
 
 
5643
 
 
5644
/*
 
5645
 *-----------------------------------------------------------------------------
 
5646
 *
 
5647
 * HgfsServerDeleteFile --
 
5648
 *
 
5649
 *    Handle a Delete File request.
 
5650
 *
 
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.
 
5654
 *
 
5655
 *    Enforcing read-only shares restrictions
 
5656
 *
 
5657
 * Results:
 
5658
 *    None.
 
5659
 *
 
5660
 * Side effects:
 
5661
 *    None
 
5662
 *
 
5663
 *-----------------------------------------------------------------------------
 
5664
 */
 
5665
 
 
5666
static void
 
5667
HgfsServerDeleteFile(HgfsInputParam *input)  // IN: Input params
 
5668
{
 
5669
   char *cpName;
 
5670
   size_t cpNameSize;
 
5671
   HgfsServerLock serverLock = HGFS_LOCK_NONE;
 
5672
   fileDesc fileDesc;
 
5673
   HgfsHandle file;
 
5674
   HgfsDeleteHint hints = 0;
 
5675
   HgfsInternalStatus status;
 
5676
   HgfsNameStatus nameStatus;
 
5677
   uint32 caseFlags;
 
5678
   size_t replyPayloadSize = 0;
 
5679
   HgfsShareInfo shareInfo;
 
5680
 
 
5681
   HGFS_ASSERT_INPUT(input);
 
5682
 
 
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);
 
5687
      } else {
 
5688
         char *utf8Name = NULL;
 
5689
         size_t utf8NameLen;
 
5690
 
 
5691
         nameStatus = HgfsServerGetShareInfo(cpName, cpNameSize, caseFlags, &shareInfo,
 
5692
                                             &utf8Name, &utf8NameLen);
 
5693
         if (nameStatus == HGFS_NAME_STATUS_COMPLETE) {
 
5694
            /*
 
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.
 
5698
             */
 
5699
            if (!shareInfo.writePermissions || !shareInfo.readPermissions) {
 
5700
               status = HgfsPlatformFileExists(utf8Name);
 
5701
               if (HGFS_ERROR_SUCCESS == status) {
 
5702
                  status = HGFS_ERROR_ACCESS_DENIED;
 
5703
               }
 
5704
               LOG(4, ("HgfsServerDeleteFile: failed access check, error %d\n", status));
 
5705
            } else if (HgfsFileHasServerLock(utf8Name, input->session, &serverLock,
 
5706
                       &fileDesc)) {
 
5707
               /*
 
5708
                * XXX: If the file has an oplock, the client should have broken it on
 
5709
                * its own by now. Sorry!
 
5710
                */
 
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;
 
5714
            } else {
 
5715
               LOG(4, ("%s: deleting \"%s\"\n", __FUNCTION__, utf8Name));
 
5716
               status = HgfsPlatformDeleteFileByName(utf8Name);
 
5717
            }
 
5718
            free(utf8Name);
 
5719
         } else {
 
5720
            LOG(4, ("%s: Shared folder does not exist.\n", __FUNCTION__));
 
5721
            status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
5722
         }
 
5723
      }
 
5724
      if (HGFS_ERROR_SUCCESS == status) {
 
5725
         if (!HgfsPackDeleteReply(input->packet, input->metaPacket, input->op,
 
5726
                                  &replyPayloadSize, input->session)) {
 
5727
            status = HGFS_ERROR_INTERNAL;
 
5728
         }
 
5729
      }
 
5730
   } else {
 
5731
      status = HGFS_ERROR_PROTOCOL;
 
5732
   }
 
5733
 
 
5734
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
5735
}
 
5736
 
 
5737
 
 
5738
/*
 
5739
 *-----------------------------------------------------------------------------
 
5740
 *
 
5741
 * HgfsServerDeleteDir --
 
5742
 *
 
5743
 *    Handle a Delete Dir request.
 
5744
 *
 
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.
 
5748
 *
 
5749
 * Results:
 
5750
 *    None.
 
5751
 *
 
5752
 * Side effects:
 
5753
 *    None
 
5754
 *
 
5755
 *-----------------------------------------------------------------------------
 
5756
 */
 
5757
 
 
5758
static void
 
5759
HgfsServerDeleteDir(HgfsInputParam *input)  // IN: Input params
 
5760
{
 
5761
   char *cpName;
 
5762
   size_t cpNameSize;
 
5763
   HgfsInternalStatus status;
 
5764
   HgfsNameStatus nameStatus;
 
5765
   HgfsHandle file;
 
5766
   HgfsDeleteHint hints = 0;
 
5767
   fileDesc fileDesc;
 
5768
   Bool sharedFolderOpen = FALSE;
 
5769
   uint32 caseFlags;
 
5770
   size_t replyPayloadSize = 0;
 
5771
   HgfsShareInfo shareInfo;
 
5772
 
 
5773
   HGFS_ASSERT_INPUT(input);
 
5774
 
 
5775
   if (HgfsUnpackDeleteRequest(input->payload, input->payloadSize, input->op, &cpName,
 
5776
                               &cpNameSize, &hints, &file, &caseFlags)) {
 
5777
      if (hints & HGFS_DELETE_HINT_USE_FILE_DESC) {
 
5778
 
 
5779
         status = HgfsPlatformGetFd(file, input->session, FALSE, &fileDesc);
 
5780
 
 
5781
         if (HGFS_ERROR_SUCCESS == status) {
 
5782
            if (HgfsHandleIsSharedFolderOpen(file, input->session, &sharedFolderOpen) &&
 
5783
               sharedFolderOpen) {
 
5784
               LOG(4, ("%s: Cannot delete shared folder\n", __FUNCTION__));
 
5785
               status = HGFS_ERROR_ACCESS_DENIED;
 
5786
            } else {
 
5787
               status = HgfsPlatformDeleteDirByHandle(file, input->session);
 
5788
               if (HGFS_ERROR_SUCCESS != status) {
 
5789
                  LOG(4, ("%s: error deleting directory %d: %d\n", __FUNCTION__,
 
5790
                     file, status));
 
5791
               }
 
5792
            }
 
5793
         } else {
 
5794
            LOG(4, ("%s: could not map cached handle %u, error %u\n",
 
5795
               __FUNCTION__, file, status));
 
5796
         }
 
5797
      } else {
 
5798
         char *utf8Name = NULL;
 
5799
         size_t utf8NameLen;
 
5800
 
 
5801
         nameStatus = HgfsServerGetShareInfo(cpName, cpNameSize, caseFlags, &shareInfo,
 
5802
                                             &utf8Name, &utf8NameLen);
 
5803
         if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
 
5804
            ASSERT(utf8Name);
 
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) {
 
5810
               /*
 
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.
 
5814
                */
 
5815
               status = HgfsPlatformFileExists(utf8Name);
 
5816
               if (HGFS_ERROR_SUCCESS == status) {
 
5817
                  status = HGFS_ERROR_ACCESS_DENIED;
 
5818
               }
 
5819
               LOG(4, ("HgfsServerDeleteDir: failed access check, error %d\n", status));
 
5820
            } else {
 
5821
               LOG(4, ("%s: removing \"%s\"\n", __FUNCTION__, utf8Name));
 
5822
               status = HgfsPlatformDeleteDirByName(utf8Name);
 
5823
            }
 
5824
            free(utf8Name);
 
5825
         } else {
 
5826
            LOG(4, ("%s: access check failed\n", __FUNCTION__));
 
5827
            status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
5828
         }
 
5829
      }
 
5830
      if (HGFS_ERROR_SUCCESS == status) {
 
5831
         if (!HgfsPackDeleteReply(input->packet, input->metaPacket, input->op,
 
5832
                                  &replyPayloadSize, input->session)) {
 
5833
            status = HGFS_ERROR_INTERNAL;
 
5834
         }
 
5835
      }
 
5836
   } else {
 
5837
      status = HGFS_ERROR_PROTOCOL;
 
5838
   }
 
5839
 
 
5840
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
5841
}
 
5842
 
 
5843
 
 
5844
/*
 
5845
 *-----------------------------------------------------------------------------
 
5846
 *
 
5847
 * HgfsServerServerLockChange --
 
5848
 *
 
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.
 
5852
 *
 
5853
 * Results:
 
5854
 *    None.
 
5855
 *
 
5856
 * Side effects:
 
5857
 *    None
 
5858
 *
 
5859
 *-----------------------------------------------------------------------------
 
5860
 */
 
5861
 
 
5862
static void
 
5863
HgfsServerServerLockChange(HgfsInputParam *input)  // IN: Input params
 
5864
{
 
5865
 
 
5866
   HGFS_ASSERT_INPUT(input);
 
5867
 
 
5868
   HgfsServerCompleteRequest(HGFS_ERROR_NOT_SUPPORTED, 0, input);
 
5869
}
 
5870
 
 
5871
 
 
5872
/*
 
5873
 *-----------------------------------------------------------------------------
 
5874
 *
 
5875
 * HgfsServerWriteWin32Stream --
 
5876
 *
 
5877
 *    Handle a write request in the WIN32_STREAM_ID format.
 
5878
 *
 
5879
 * Results:
 
5880
 *    ERROR_SUCCESS or an appropriate Win32 error code.
 
5881
 *
 
5882
 * Side effects:
 
5883
 *    None
 
5884
 *
 
5885
 *-----------------------------------------------------------------------------
 
5886
 */
 
5887
 
 
5888
static void
 
5889
HgfsServerWriteWin32Stream(HgfsInputParam *input)  // IN: Input params
 
5890
{
 
5891
   uint32  actualSize;
 
5892
   HgfsInternalStatus status;
 
5893
   HgfsHandle file;
 
5894
   char *dataToWrite;
 
5895
   Bool doSecurity;
 
5896
   size_t replyPayloadSize = 0;
 
5897
   size_t requiredSize;
 
5898
 
 
5899
   HGFS_ASSERT_INPUT(input);
 
5900
 
 
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,
 
5908
                                            input->session)) {
 
5909
            status = HGFS_ERROR_INTERNAL;
 
5910
         }
 
5911
      }
 
5912
   } else {
 
5913
      status = HGFS_ERROR_PROTOCOL;
 
5914
   }
 
5915
 
 
5916
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
5917
}
 
5918
 
 
5919
 
 
5920
/*
 
5921
 *-----------------------------------------------------------------------------
 
5922
 *
 
5923
 * HgfsServerGetattr --
 
5924
 *
 
5925
 *    Handle a Getattr request.
 
5926
 *
 
5927
 * Results:
 
5928
 *    None.
 
5929
 *
 
5930
 * Side effects:
 
5931
 *    None
 
5932
 *
 
5933
 *-----------------------------------------------------------------------------
 
5934
 */
 
5935
 
 
5936
static void
 
5937
HgfsServerGetattr(HgfsInputParam *input)  // IN: Input params
 
5938
{
 
5939
   char *localName;
 
5940
   HgfsAttrHint hints = 0;
 
5941
   HgfsFileAttrInfo attr;
 
5942
   HgfsInternalStatus status = 0;
 
5943
   HgfsNameStatus nameStatus;
 
5944
   char *cpName;
 
5945
   size_t cpNameSize;
 
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;
 
5954
 
 
5955
   HGFS_ASSERT_INPUT(input);
 
5956
 
 
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) {
 
5961
         fileDesc fd;
 
5962
 
 
5963
         targetNameLen = 0;
 
5964
         status = HgfsPlatformGetFd(file, input->session, FALSE, &fd);
 
5965
         if (HGFS_ERROR_SUCCESS == status) {
 
5966
            status = HgfsPlatformGetattrFromFd(fd, input->session, &attr);
 
5967
         } else {
 
5968
            LOG(4, ("%s: Could not get file descriptor\n", __FUNCTION__));
 
5969
         }
 
5970
 
 
5971
      } else {
 
5972
         /*
 
5973
          * Depending on whether this file/dir is real or virtual, either
 
5974
          * forge its attributes or look them up in the actual filesystem.
 
5975
          */
 
5976
         nameStatus = HgfsServerGetShareInfo(cpName, cpNameSize, caseFlags, &shareInfo,
 
5977
                                             &localName, &localNameLen);
 
5978
         switch (nameStatus) {
 
5979
         case HGFS_NAME_STATUS_INCOMPLETE_BASE:
 
5980
            /*
 
5981
             * This is the base of our namespace; make up fake status for
 
5982
             * this directory.
 
5983
             */
 
5984
 
 
5985
            LOG(4, ("%s: getting attrs for base dir\n", __FUNCTION__));
 
5986
            HgfsPlatformGetDefaultDirAttrs(&attr);
 
5987
            break;
 
5988
 
 
5989
         case HGFS_NAME_STATUS_COMPLETE:
 
5990
            /* This is a regular lookup; proceed as usual */
 
5991
            ASSERT(localName);
 
5992
 
 
5993
            /* Get the config options. */
 
5994
            nameStatus = HgfsServerPolicy_GetShareOptions(cpName, cpNameSize,
 
5995
                                                          &configOptions);
 
5996
            if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
 
5997
               status = HgfsPlatformGetattrFromName(localName, configOptions, cpName, &attr,
 
5998
                                                    &targetName);
 
5999
            } else {
 
6000
               LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, cpName));
 
6001
               status = HGFS_ERROR_FILE_NOT_FOUND;
 
6002
            }
 
6003
            free(localName);
 
6004
 
 
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) {
 
6011
               /*
 
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"
 
6016
                * error.
 
6017
                * Replace it with a more appropriate error code: no such device.
 
6018
                */
 
6019
               if (status == HGFS_ERROR_FILE_NOT_FOUND &&
 
6020
                   HgfsIsShareRoot(cpName, cpNameSize)) {
 
6021
                  status = HGFS_ERROR_IO;
 
6022
               }
 
6023
            }
 
6024
            break;
 
6025
 
 
6026
         default:
 
6027
            status = HgfsPlatformHandleIncompleteName(nameStatus, &attr);
 
6028
         }
 
6029
         targetNameLen = targetName ? strlen(targetName) : 0;
 
6030
 
 
6031
      }
 
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;
 
6036
         }
 
6037
      }
 
6038
   } else {
 
6039
      status = HGFS_ERROR_PROTOCOL;
 
6040
   }
 
6041
 
 
6042
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
6043
}
 
6044
 
 
6045
 
 
6046
/*
 
6047
 *-----------------------------------------------------------------------------
 
6048
 *
 
6049
 * HgfsServerSetattr --
 
6050
 *
 
6051
 *    Handle a Setattr request.
 
6052
 *
 
6053
 * Results:
 
6054
 *    None.
 
6055
 *
 
6056
 * Side effects:
 
6057
 *    None
 
6058
 *
 
6059
 *-----------------------------------------------------------------------------
 
6060
 */
 
6061
 
 
6062
static void
 
6063
HgfsServerSetattr(HgfsInputParam *input)  // IN: Input params
 
6064
{
 
6065
   HgfsInternalStatus status = HGFS_ERROR_SUCCESS;
 
6066
   HgfsNameStatus nameStatus;
 
6067
   HgfsFileAttrInfo attr;
 
6068
   char *cpName;
 
6069
   size_t cpNameSize = 0;
 
6070
   HgfsAttrHint hints = 0;
 
6071
   HgfsOpenMode shareMode;
 
6072
   uint32 caseFlags = 0;
 
6073
   HgfsShareInfo shareInfo;
 
6074
   HgfsHandle file;
 
6075
   size_t replyPayloadSize = 0;
 
6076
 
 
6077
   HGFS_ASSERT_INPUT(input);
 
6078
 
 
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);
 
6086
            } else {
 
6087
               status = HGFS_ERROR_ACCESS_DENIED;
 
6088
            }
 
6089
         } else {
 
6090
            LOG(4, ("%s: could not get share mode fd %d\n", __FUNCTION__,
 
6091
                file));
 
6092
            status = HGFS_ERROR_INVALID_HANDLE;
 
6093
         }
 
6094
      } else { /* Client wants us to open a new handle for this operation. */
 
6095
         char *utf8Name = NULL;
 
6096
         size_t utf8NameLen;
 
6097
 
 
6098
         nameStatus = HgfsServerGetShareInfo(cpName, cpNameSize, caseFlags, &shareInfo,
 
6099
                                             &utf8Name, &utf8NameLen);
 
6100
         if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
 
6101
            fileDesc hFile;
 
6102
            HgfsServerLock serverLock = HGFS_LOCK_NONE;
 
6103
            HgfsShareOptions configOptions;
 
6104
 
 
6105
            /*
 
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.
 
6109
             */
 
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,
 
6116
                       &configOptions)) {
 
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",
 
6122
                      __FUNCTION__));
 
6123
               status = HGFS_ERROR_PATH_BUSY;
 
6124
            } else {
 
6125
               status = HgfsPlatformSetattrFromName(utf8Name, &attr, configOptions, hints);
 
6126
            }
 
6127
            free(utf8Name);
 
6128
         } else {
 
6129
            LOG(4, ("%s: file not found.\n", __FUNCTION__));
 
6130
            status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
6131
         }
 
6132
      }
 
6133
 
 
6134
      if (HGFS_ERROR_SUCCESS == status) {
 
6135
         if (!HgfsPackSetattrReply(input->packet, input->metaPacket, attr.requestType,
 
6136
                                   &replyPayloadSize, input->session)) {
 
6137
            status = HGFS_ERROR_INTERNAL;
 
6138
         }
 
6139
      }
 
6140
   } else {
 
6141
      status = HGFS_ERROR_PROTOCOL;
 
6142
   }
 
6143
 
 
6144
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
6145
}
 
6146
 
 
6147
 
 
6148
/*
 
6149
 *-----------------------------------------------------------------------------
 
6150
 *
 
6151
 * HgfsServerValidateOpenParameters --
 
6152
 *
 
6153
 *    Performs sanity check of the input parameters.
 
6154
 *
 
6155
 * Results:
 
6156
 *    HGFS_ERROR_SUCCESS if the parameters are valid.
 
6157
 *    Appropriate error code otherwise.
 
6158
 *
 
6159
 * Side effects:
 
6160
 *    None
 
6161
 *
 
6162
 *-----------------------------------------------------------------------------
 
6163
 */
 
6164
 
 
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
 
6169
{
 
6170
   size_t utf8NameLen;
 
6171
   HgfsInternalStatus status;
 
6172
 
 
6173
   *followSymlinks = 0;
 
6174
   *denyCreatingFile = FALSE;
 
6175
 
 
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,
 
6184
                                          &utf8NameLen);
 
6185
      if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
 
6186
         if (openInfo->mask & HGFS_OPEN_VALID_FLAGS) {
 
6187
            HgfsOpenFlags savedOpenFlags = openInfo->flags;
 
6188
 
 
6189
            if (HgfsServerCheckOpenFlagsForShare(openInfo, &openInfo->flags)) {
 
6190
               HgfsShareOptions configOptions;
 
6191
 
 
6192
               /* Get the config options. */
 
6193
               nameStatus = HgfsServerPolicy_GetShareOptions(openInfo->cpName,
 
6194
                                                             openInfo->cpNameSize,
 
6195
                                                             &configOptions);
 
6196
               if (nameStatus == HGFS_NAME_STATUS_COMPLETE) {
 
6197
                  *followSymlinks =
 
6198
                     HgfsServerPolicy_IsShareOptionSet(configOptions,
 
6199
                                                       HGFS_SHARE_FOLLOW_SYMLINKS);
 
6200
                  *denyCreatingFile = savedOpenFlags != openInfo->flags;
 
6201
                  status = HGFS_ERROR_SUCCESS;
 
6202
               } else {
 
6203
                  LOG(4, ("%s: no matching share: %s.\n", __FUNCTION__, openInfo->cpName));
 
6204
                  *denyCreatingFile = TRUE;
 
6205
                  status = HGFS_ERROR_FILE_NOT_FOUND;
 
6206
               }
 
6207
            } else {
 
6208
               /* Incompatible open mode with share mode. */
 
6209
               status = HGFS_STATUS_ACCESS_DENIED;
 
6210
            }
 
6211
         } else {
 
6212
            status = HGFS_ERROR_PROTOCOL;
 
6213
         }
 
6214
      } else {
 
6215
         /*
 
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.
 
6222
          */
 
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__));
 
6232
            } else {
 
6233
               LOG(4, ("%s: Shared folder not found\n", __FUNCTION__));
 
6234
            }
 
6235
         } else {
 
6236
            LOG(4, ("%s: Shared folder access error %u\n", __FUNCTION__, nameStatus));
 
6237
         }
 
6238
         status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
6239
      }
 
6240
   } else {
 
6241
      LOG(4, ("%s: filename or mode not provided\n", __FUNCTION__));
 
6242
      status = HGFS_ERROR_PROTOCOL;
 
6243
   }
 
6244
   return status;
 
6245
}
 
6246
 
 
6247
 
 
6248
/*
 
6249
 *-----------------------------------------------------------------------------
 
6250
 *
 
6251
 * HgfsServerOpen --
 
6252
 *
 
6253
 *    Handle an Open request.
 
6254
 *
 
6255
 * Results:
 
6256
 *    None.
 
6257
 *
 
6258
 * Side effects:
 
6259
 *    None
 
6260
 *
 
6261
 *-----------------------------------------------------------------------------
 
6262
 */
 
6263
 
 
6264
static void
 
6265
HgfsServerOpen(HgfsInputParam *input)  // IN: Input params
 
6266
{
 
6267
   HgfsInternalStatus status;
 
6268
   fileDesc newHandle;
 
6269
   HgfsLocalId localId;
 
6270
   HgfsFileOpenInfo openInfo;
 
6271
   fileDesc fileDesc;
 
6272
   HgfsServerLock serverLock = HGFS_LOCK_NONE;
 
6273
   size_t replyPayloadSize = 0;
 
6274
 
 
6275
   HGFS_ASSERT_INPUT(input);
 
6276
 
 
6277
   if (HgfsUnpackOpenRequest(input->payload, input->payloadSize, input->op, &openInfo)) {
 
6278
      int followSymlinks;
 
6279
      Bool denyCreatingFile;
 
6280
 
 
6281
      status = HgfsServerValidateOpenParameters(&openInfo, &denyCreatingFile,
 
6282
                                                &followSymlinks);
 
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));
 
6297
         /*
 
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.
 
6303
          *
 
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.
 
6307
          *
 
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.
 
6311
          */
 
6312
         if (!HgfsFileHasServerLock(openInfo.utf8Name, input->session, &serverLock,
 
6313
                                    &fileDesc)) {
 
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);
 
6319
 
 
6320
               /*
 
6321
                * Open succeeded, so make new node and return its handle. If we fail,
 
6322
                * it's almost certainly an internal server error.
 
6323
                */
 
6324
 
 
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;
 
6330
                  }
 
6331
               }
 
6332
            } else if (denyCreatingFile && HGFS_ERROR_FILE_NOT_FOUND == status) {
 
6333
               status = HGFS_ERROR_ACCESS_DENIED;
 
6334
            }
 
6335
         } else {
 
6336
            status = HGFS_ERROR_PATH_BUSY;
 
6337
         }
 
6338
         free(openInfo.utf8Name);
 
6339
      }
 
6340
   } else {
 
6341
      status = HGFS_ERROR_PROTOCOL;
 
6342
   }
 
6343
 
 
6344
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
6345
}
 
6346
 
 
6347
 
 
6348
/*
 
6349
 *-----------------------------------------------------------------------------
 
6350
 *
 
6351
 * HgfsGetDirEntry --
 
6352
 *
 
6353
 *    Gets a directory entry at specified offset.
 
6354
 *
 
6355
 * Results:
 
6356
 *    None.
 
6357
 *
 
6358
 * Side effects:
 
6359
 *    None
 
6360
 *
 
6361
 *-----------------------------------------------------------------------------
 
6362
 */
 
6363
 
 
6364
static HgfsInternalStatus
 
6365
HgfsGetDirEntry(HgfsHandle hgfsSearchHandle,
 
6366
                uint32 requestedOffset,
 
6367
                HgfsSearch *search,
 
6368
                HgfsShareOptions configOptions,
 
6369
                HgfsSessionInfo *session,
 
6370
                HgfsFileAttrInfo *attr,
 
6371
                char **entryName,
 
6372
                size_t *nameLength)
 
6373
{
 
6374
   HgfsInternalStatus status;
 
6375
   DirectoryEntry *dent;
 
6376
 
 
6377
   dent = HgfsGetSearchResult(hgfsSearchHandle, session, requestedOffset, FALSE);
 
6378
   if (dent) {
 
6379
      unsigned int length;
 
6380
      char *fullName;
 
6381
      char *sharePath;
 
6382
      size_t sharePathLen;
 
6383
      size_t fullNameLen;
 
6384
      HgfsServerLock serverLock = HGFS_LOCK_NONE;
 
6385
      fileDesc fileDesc;
 
6386
 
 
6387
      length = strlen(dent->d_name);
 
6388
 
 
6389
      /* Each type of search gets a dent's attributes in a different way. */
 
6390
      switch (search->type) {
 
6391
      case DIRECTORY_SEARCH_TYPE_DIR:
 
6392
 
 
6393
         /*
 
6394
          * Construct the UTF8 version of the full path to the file, and call
 
6395
          * HgfsGetattrFromName to get the attributes of the file.
 
6396
          */
 
6397
         fullNameLen = search->utf8DirLen + 1 + length;
 
6398
         fullName = (char *)malloc(fullNameLen + 1);
 
6399
         if (fullName) {
 
6400
            memcpy(fullName, search->utf8Dir, search->utf8DirLen);
 
6401
            fullName[search->utf8DirLen] = DIRSEPC;
 
6402
            memcpy(&fullName[search->utf8DirLen + 1], dent->d_name, length + 1);
 
6403
 
 
6404
            LOG(4, ("%s: about to stat \"%s\"\n", __FUNCTION__, fullName));
 
6405
 
 
6406
            /*
 
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.
 
6411
             *
 
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.
 
6417
             *
 
6418
             * XXX: We could open a new handle safely if its a shared oplock.
 
6419
             * But isn't this handle sharing always desirable?
 
6420
             */
 
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);
 
6425
            } else {
 
6426
               status = HgfsPlatformGetattrFromName(fullName, configOptions,
 
6427
                                                    search->utf8ShareName, attr, NULL);
 
6428
            }
 
6429
 
 
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;
 
6436
               attr->mask = 0;
 
6437
            }
 
6438
 
 
6439
            free(fullName);
 
6440
            status = HGFS_ERROR_SUCCESS;
 
6441
         } else {
 
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;
 
6445
         }
 
6446
         break;
 
6447
 
 
6448
      case DIRECTORY_SEARCH_TYPE_BASE:
 
6449
 
 
6450
         /*
 
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.
 
6455
          */
 
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;
 
6462
         } else {
 
6463
            HgfsNameStatus nameStatus;
 
6464
 
 
6465
            /* Check permission on the share and get the share path */
 
6466
            nameStatus =
 
6467
               HgfsServerPolicy_GetSharePath(dent->d_name, length,
 
6468
                                             HGFS_OPEN_MODE_READ_ONLY,
 
6469
                                             &sharePathLen,
 
6470
                                             (char const **)&sharePath);
 
6471
            if (nameStatus == HGFS_NAME_STATUS_COMPLETE) {
 
6472
 
 
6473
               /*
 
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.
 
6478
                */
 
6479
               /*
 
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.
 
6483
                */
 
6484
               status = HgfsPlatformGetattrFromName(sharePath, configOptions,
 
6485
                                                    dent->d_name, attr, NULL);
 
6486
 
 
6487
               /*
 
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
 
6496
                * are not set.
 
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.
 
6501
                *
 
6502
                * See bug 125065.
 
6503
                */
 
6504
               attr->flags &= ~(HGFS_ATTR_HIDDEN | HGFS_ATTR_SYSTEM);
 
6505
 
 
6506
               if (HGFS_ERROR_SUCCESS != status) {
 
6507
                  /*
 
6508
                   * The dent no longer exists. Log the event.
 
6509
                   */
 
6510
 
 
6511
                  LOG(4, ("%s: stat FAILED\n", __FUNCTION__));
 
6512
                  status = HGFS_ERROR_SUCCESS;
 
6513
               }
 
6514
            } else {
 
6515
               LOG(4, ("%s: No such share or access denied\n", __FUNCTION__));
 
6516
               status = HgfsPlatformConvertFromNameStatus(nameStatus);
 
6517
            }
 
6518
         }
 
6519
         break;
 
6520
      case DIRECTORY_SEARCH_TYPE_OTHER:
 
6521
 
 
6522
         /*
 
6523
          * The POSIX implementation of HgfsSearchOpen could not have created
 
6524
          * this kind of search.
 
6525
          */
 
6526
#if !defined(_WIN32)
 
6527
         NOT_IMPLEMENTED();
 
6528
#endif
 
6529
         /*
 
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).
 
6533
          */
 
6534
         HgfsPlatformGetDefaultDirAttrs(attr);
 
6535
         break;
 
6536
      default:
 
6537
         NOT_IMPLEMENTED();
 
6538
         break;
 
6539
      }
 
6540
 
 
6541
      /*
 
6542
       * We need to unescape the name before sending it back to the client
 
6543
       */
 
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));
 
6549
      } else {
 
6550
         *entryName = NULL;
 
6551
         *nameLength = 0;
 
6552
         LOG(4, ("%s: error %d getting dent\n", __FUNCTION__, status));
 
6553
      }
 
6554
 
 
6555
      free(dent);
 
6556
   } else {
 
6557
      /* End of directory entries marker. */
 
6558
      *entryName = NULL;
 
6559
      *nameLength = 0;
 
6560
      status = HGFS_ERROR_SUCCESS;
 
6561
   }
 
6562
   return status;
 
6563
}
 
6564
 
 
6565
 
 
6566
/*
 
6567
 *-----------------------------------------------------------------------------
 
6568
 *
 
6569
 * HgfsServerSearchRead --
 
6570
 *
 
6571
 *    Handle a "Search Read" request.
 
6572
 *
 
6573
 * Results:
 
6574
 *    None.
 
6575
 *
 
6576
 * Side effects:
 
6577
 *    None
 
6578
 *
 
6579
 *-----------------------------------------------------------------------------
 
6580
 */
 
6581
 
 
6582
static void
 
6583
HgfsServerSearchRead(HgfsInputParam *input)  // IN: Input params
 
6584
{
 
6585
   uint32 requestedOffset;
 
6586
   HgfsFileAttrInfo attr;
 
6587
   HgfsInternalStatus status;
 
6588
   HgfsNameStatus nameStatus;
 
6589
   HgfsHandle hgfsSearchHandle;
 
6590
   HgfsSearch search;
 
6591
   HgfsShareOptions configOptions = 0;
 
6592
   size_t replyPayloadSize = 0;
 
6593
   char *entryName;
 
6594
   size_t nameLength;
 
6595
 
 
6596
   HGFS_ASSERT_INPUT(input);
 
6597
 
 
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,
 
6608
                                                          &configOptions);
 
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;
 
6613
            }
 
6614
         }
 
6615
 
 
6616
         if (HGFS_ERROR_SUCCESS == status) {
 
6617
            status = HgfsGetDirEntry(hgfsSearchHandle, requestedOffset, &search,
 
6618
                                     configOptions, input->session, &attr, &entryName,
 
6619
                                     &nameLength);
 
6620
            if (HGFS_ERROR_SUCCESS == status) {
 
6621
               if (!HgfsPackSearchReadReply(input->packet, input->metaPacket, entryName,
 
6622
                                            nameLength, &attr, &replyPayloadSize,
 
6623
                                            input->session)) {
 
6624
                  status = HGFS_ERROR_INTERNAL;
 
6625
               }
 
6626
               free(entryName);
 
6627
            }
 
6628
         }
 
6629
 
 
6630
         free(search.utf8Dir);
 
6631
         free(search.utf8ShareName);
 
6632
      } else {
 
6633
         LOG(4, ("%s: handle %u is invalid\n", __FUNCTION__, hgfsSearchHandle));
 
6634
         status = HGFS_ERROR_INVALID_HANDLE;
 
6635
      }
 
6636
   } else {
 
6637
      status = HGFS_ERROR_PROTOCOL;
 
6638
   }
 
6639
 
 
6640
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
6641
}
 
6642
 
 
6643
 
 
6644
/*
 
6645
 *-----------------------------------------------------------------------------
 
6646
 *
 
6647
 * HgfsServerCreateSession --
 
6648
 *
 
6649
 *    Handle a "Create session" request.
 
6650
 *
 
6651
 * Results:
 
6652
 *    None.
 
6653
 *
 
6654
 * Side effects:
 
6655
 *    None
 
6656
 *
 
6657
 *-----------------------------------------------------------------------------
 
6658
 */
 
6659
 
 
6660
static void
 
6661
HgfsServerCreateSession(HgfsInputParam *input)  // IN: Input params
 
6662
{
 
6663
   size_t replyPayloadSize = 0;
 
6664
   HgfsCreateSessionInfo info;
 
6665
   HgfsInternalStatus status;
 
6666
 
 
6667
   HGFS_ASSERT_INPUT(input);
 
6668
 
 
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;
 
6674
      }
 
6675
      if (HgfsPackCreateSessionReply(input->packet, input->metaPacket,
 
6676
                                     &replyPayloadSize, input->session)) {
 
6677
         HgfsServerSessionGet(input->session);
 
6678
         status = HGFS_ERROR_SUCCESS;
 
6679
      } else {
 
6680
         status = HGFS_ERROR_INTERNAL;
 
6681
      }
 
6682
   } else {
 
6683
      status = HGFS_ERROR_PROTOCOL;
 
6684
   }
 
6685
 
 
6686
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
 
6687
}
 
6688
 
 
6689
 
 
6690
/*
 
6691
 *-----------------------------------------------------------------------------
 
6692
 *
 
6693
 * HgfsServerDestroySession --
 
6694
 *
 
6695
 *    Handle a "Destroy session" request.
 
6696
 *
 
6697
 * Results:
 
6698
 *    None.
 
6699
 *
 
6700
 * Side effects:
 
6701
 *    None
 
6702
 *
 
6703
 *-----------------------------------------------------------------------------
 
6704
 */
 
6705
 
 
6706
static void
 
6707
HgfsServerDestroySession(HgfsInputParam *input)  // IN: Input params
 
6708
{
 
6709
   HGFS_ASSERT_INPUT(input);
 
6710
 
 
6711
   HgfsServerCompleteRequest(HGFS_ERROR_SUCCESS, 0, input);
 
6712
   HgfsServerSessionPut(input->session);
 
6713
}
8183
6714
 
8184
6715
 
8185
6716
/*
8302
6833
 */
8303
6834
 
8304
6835
void
8305
 
Hgfs_NotificationCallback(SharedFolderHandle sharedFolder,
8306
 
                          SubscriberHandle subscriber,
 
6836
Hgfs_NotificationCallback(HgfsSharedFolderHandle sharedFolder,
 
6837
                          HgfsSubscriberHandle subscriber,
8307
6838
                          char* name,
8308
6839
                          char* newName,
8309
6840
                          uint32 mask)
8314
6845
            mask));
8315
6846
}
8316
6847
 
 
6848
 
 
6849
/*
 
6850
 *-----------------------------------------------------------------------------
 
6851
 *
 
6852
 * HgfsIsShareRoot --
 
6853
 *
 
6854
 *    Checks if the cpName represents the root directory for a share.
 
6855
 *    Components in CPName format are separated by NUL characters.
 
6856
 *    CPName for the root of a share contains only one component thus
 
6857
 *    it does not have any embedded '\0' characters in the name.
 
6858
 *
 
6859
 * Results:
 
6860
 *    TRUE if it is the root directory, FALSE otherwise.
 
6861
 *
 
6862
 * Side effects:
 
6863
 *    None
 
6864
 *
 
6865
 *-----------------------------------------------------------------------------
 
6866
 */
 
6867
 
 
6868
static Bool
 
6869
HgfsIsShareRoot(char const *cpName,         // IN: name to test
 
6870
                size_t cpNameSize)          // IN: length of the name
 
6871
{
 
6872
   size_t i;
 
6873
   for (i = 0; i < cpNameSize; i++) {
 
6874
      if (cpName[i] == '\0') {
 
6875
         return FALSE;
 
6876
      }
 
6877
   }
 
6878
   return TRUE;
 
6879
}
 
6880
 
8317
6881
#ifdef HGFS_OPLOCKS
8318
6882
/*
8319
6883
 *-----------------------------------------------------------------------------