~henrix/ubuntu/precise/open-vm-dkms/lp-1416003

« back to all changes in this revision

Viewing changes to lib/hgfsServer/hgfsServerLinux.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2008-10-23 15:32:00 UTC
  • mfrom: (1.1.2 upstream) (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20081023153200-gc1bfx89hj35c799
Tags: 2008.10.10-123053-2
* Correcting typo in dh_installinit call.
* Downgrading depends on module-assistant to recommends.

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
#include <sys/types.h>
41
41
#include <dirent.h>
42
42
 
 
43
#if defined(__FreeBSD__)
 
44
#   include <sys/param.h>
 
45
#else
 
46
#   include <wchar.h>
 
47
#   include <wctype.h>
 
48
#endif
 
49
 
43
50
#include "vmware.h"
44
51
#include "hgfsServerPolicy.h" // for security policy
45
52
#include "hgfsServerInt.h"
185
192
#endif
186
193
 
187
194
 
188
 
#if defined(sun) || defined(linux) || (defined(__FreeBSD__) && BSD_VERSION < 49)
 
195
#if defined(sun) || defined(linux) || \
 
196
    (defined(__FreeBSD_version) && __FreeBSD_version < 490000)
189
197
/*
190
198
 * Implements futimes(), which was introduced in glibc 2.3.3. FreeBSD 3.2
191
199
 * doesn't have it, but 4.9 does. Unfortunately, these early FreeBSD versions
258
266
                                                  char **targetName);
259
267
 
260
268
static HgfsInternalStatus HgfsGetattrFromName(char *fileName,
 
269
                                              HgfsShareOptions configOptions,
261
270
                                              HgfsFileAttrInfo *attr,
262
271
                                              char **targetName);
263
272
 
901
910
 
902
911
static HgfsInternalStatus
903
912
HgfsValidateOpen(HgfsFileOpenInfo *openInfo, // IN: Open info struct
 
913
                 int followSymlinks,         // IN: followSymlinks config option
904
914
                 HgfsLocalId *localId,       // OUT: Local unique file ID
905
915
                 int *fileDesc)              // OUT: Handle to the file
906
916
{
949
959
                  openInfo->otherPerms : (openPerms & S_IRWXU) >> 6;
950
960
 
951
961
   /*
 
962
    * By default we don't follow symlinks, O_NOFOLLOW is always set.
 
963
    * Unset it if followSymlinks config option is specified.
 
964
    */
 
965
   if (followSymlinks) {
 
966
      openFlags &= ~O_NOFOLLOW;
 
967
   }
 
968
 
 
969
   /*
952
970
    * Try to open the file with the requested mode, flags and permissions.
953
971
    */
954
972
   fd = Posix_Open(openInfo->utf8Name,
1330
1348
      goto exit;
1331
1349
   }
1332
1350
 
 
1351
   /* 
 
1352
    * Unicode_CompareIgnoreCase crashes with invalid unicode strings,
 
1353
    * validate it before passing it to Unicode_* functions.
 
1354
    */
 
1355
   if (!Unicode_IsBufferValid(currentComponent, -1, STRING_ENCODING_UTF8)) {
 
1356
      /* Invalid unicode string, return failure. */
 
1357
      ret = EINVAL;
 
1358
      goto exit;
 
1359
   }
 
1360
 
1333
1361
   /*
1334
1362
    * Read all of the directory entries. For each one, convert the name
1335
1363
    * to lower case and then compare it to the lower case component.
1336
1364
    */
1337
1365
   while ((dirent = readdir(dir))) {
 
1366
      Unicode dentryNameU;
 
1367
      int cmpResult;
 
1368
 
1338
1369
      dentryName = dirent->d_name;
1339
1370
      dentryNameLen = strlen(dentryName);
1340
1371
 
1341
 
      if (Unicode_CompareIgnoreCase(currentComponent, dentryName) == 0) {
 
1372
      /* 
 
1373
       * Unicode_CompareIgnoreCase crashes with invalid unicode strings,
 
1374
       * validate and convert it appropriately before passing it to Unicode_* functions.
 
1375
       */
 
1376
      if (!Unicode_IsBufferValid(dentryName, dentryNameLen, STRING_ENCODING_DEFAULT)) {
 
1377
         /* Invalid unicode string, skip the entry. */
 
1378
         continue;
 
1379
      }
 
1380
 
 
1381
      dentryNameU = Unicode_Alloc(dentryName, STRING_ENCODING_DEFAULT);
 
1382
 
 
1383
      cmpResult = Unicode_CompareIgnoreCase(currentComponent, dentryNameU);
 
1384
      Unicode_Free(dentryNameU);
 
1385
 
 
1386
      if (cmpResult == 0) {
1342
1387
         /*
1343
1388
          * The current directory entry is a case insensitive match to
1344
1389
          * the specified component. Malloc and copy the current directory entry.
1701
1746
 */
1702
1747
 
1703
1748
static HgfsInternalStatus
1704
 
HgfsGetattrFromName(char *fileName,             // IN/OUT:  Input filename
1705
 
                    HgfsFileAttrInfo *attr,     // OUT: Struct to copy into
1706
 
                    char **targetName)          // OUT: Symlink target filename
 
1749
HgfsGetattrFromName(char *fileName,                    // IN/OUT:  Input filename
 
1750
                    HgfsShareOptions configOptions,    // IN: Share config options
 
1751
                    HgfsFileAttrInfo *attr,            // OUT: Struct to copy into
 
1752
                    char **targetName)                 // OUT: Symlink target filename
1707
1753
{
1708
1754
   HgfsInternalStatus status = 0;
1709
1755
   struct stat stats;
1710
1756
   int error;
1711
1757
   char *myTargetName = NULL;
1712
1758
 
 
1759
   ASSERT(fileName);
1713
1760
   ASSERT(attr);
 
1761
 
1714
1762
   LOG(4, ("HgfsGetattrFromName: getting attrs for \"%s\"\n", fileName));
1715
1763
 
1716
 
   errno = 0;
1717
 
   error = Posix_Lstat(fileName, &stats);
 
1764
   /* Check the config option to determine if we should follow symlinks. */
 
1765
   if (HgfsServerPolicy_IsShareOptionSet(configOptions, HGFS_SHARE_FOLLOW_SYMLINKS)) {
 
1766
      errno = 0;
 
1767
      error = Posix_Stat(fileName, &stats);
 
1768
   } else {
 
1769
      errno = 0;
 
1770
      error = Posix_Lstat(fileName, &stats);
 
1771
   }
 
1772
 
1718
1773
   if (error) {
1719
1774
      status = errno;
1720
1775
      LOG(4, ("HgfsGetattrFromName: error stating file: %s\n",
1983
2038
    * FreeBSD: All supported versions have timestamps with nanosecond resolution.
1984
2039
    *          FreeBSD 5+ has also file creation time.
1985
2040
    */
1986
 
#   if BSD_VERSION >= 50
 
2041
#   if __IS_FREEBSD_VER__(500043)
1987
2042
   attr->creationTime   = HgfsConvertTimeSpecToNtTime(&stats->st_birthtimespec);
1988
2043
#   else
1989
2044
   attr->creationTime   = HgfsConvertTimeSpecToNtTime(&stats->st_atimespec);
2031
2086
           attr->specialPerms, attr->ownerPerms, attr->groupPerms,
2032
2087
           attr->otherPerms, attr->size));
2033
2088
#ifdef __FreeBSD__
2034
 
#   if !defined(VM_X86_64) && BSD_VERSION >= 50
 
2089
#   if !defined(VM_X86_64) && __FreeBSD_version >= 500043
2035
2090
#      define FMTTIMET ""
2036
2091
#   else
2037
2092
#      define FMTTIMET "l"
2048
2103
   attr->userId = stats->st_uid;
2049
2104
   attr->groupId = stats->st_gid;
2050
2105
   attr->hostFileId = stats->st_ino;
 
2106
   attr->volumeId = stats->st_dev;
2051
2107
   attr->mask = HGFS_ATTR_VALID_TYPE |
2052
2108
      HGFS_ATTR_VALID_SIZE |
2053
2109
      HGFS_ATTR_VALID_CREATE_TIME |
2060
2116
      HGFS_ATTR_VALID_OTHER_PERMS |
2061
2117
      HGFS_ATTR_VALID_USERID |
2062
2118
      HGFS_ATTR_VALID_GROUPID |
2063
 
      HGFS_ATTR_VALID_FILEID;
 
2119
      HGFS_ATTR_VALID_FILEID |
 
2120
      HGFS_ATTR_VALID_VOLID;
2064
2121
}
2065
2122
 
2066
2123
 
2482
2539
                    size_t cpNameSize,        // IN: Name length
2483
2540
                    HgfsFileAttrInfo *attr,   // IN: attrs to set
2484
2541
                    HgfsAttrHint hints,       // IN: attr hints
2485
 
                    uint32 caseFlags)         // IN: case-sensitivity flags
 
2542
                    uint32 caseFlags)         // IN: case-sensitivity flags
2486
2543
{
2487
2544
   HgfsInternalStatus status = 0, timesStatus;
2488
2545
   HgfsNameStatus nameStatus;
2497
2554
   Bool timesChanged = FALSE;
2498
2555
   Bool idChanged = FALSE;
2499
2556
   HgfsServerLock serverLock;
 
2557
   HgfsShareOptions configOptions;
2500
2558
 
2501
2559
   nameStatus = HgfsServerGetAccess(cpName,
2502
2560
                                    cpNameSize,
2512
2570
 
2513
2571
   ASSERT(localName);
2514
2572
 
2515
 
   /*
2516
 
    * Verify that the pathname isn't a symlink. Some of the following
2517
 
    * syscalls (chmod, for example) will follow a link. So we need to
2518
 
    * verify the final component too. The parent has already been verified
2519
 
    * in HgfsServerGetAccess.
2520
 
    *
2521
 
    * XXX: This is racy. But clients interested in preventing a race should
2522
 
    * have sent us a Setattr packet with a valid HGFS handle.
2523
 
    */
2524
 
   if (File_IsSymLink(localName)) {
2525
 
      LOG(4, ("HgfsSetattrFromName: pathname contains a symlink\n"));
2526
 
      status = EINVAL;
2527
 
      goto exit_free;
 
2573
   /* Get the config options. */
 
2574
   nameStatus = HgfsServerPolicy_GetShareOptions(cpName, cpNameSize,
 
2575
                                                 &configOptions);
 
2576
   if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
 
2577
      LOG(4, ("HgfsSetattrFromName: no matching share: %s.\n", cpName));
 
2578
      goto exit;
 
2579
   }
 
2580
 
 
2581
   if (!HgfsServerPolicy_IsShareOptionSet(configOptions, HGFS_SHARE_FOLLOW_SYMLINKS)) {
 
2582
      /*
 
2583
       * If followSymlink option is not set, verify that the pathname isn't a
 
2584
       * symlink. Some of the following syscalls (chmod, for example) will follow
 
2585
       * a link. So we need to verify the final component too. The parent has
 
2586
       * already been verified in HgfsServerGetAccess.
 
2587
       *
 
2588
       * XXX: This is racy. But clients interested in preventing a race should
 
2589
       * have sent us a Setattr packet with a valid HGFS handle.
 
2590
       */
 
2591
      if (File_IsSymLink(localName)) {
 
2592
         LOG(4, ("HgfsSetattrFromName: pathname contains a symlink\n"));
 
2593
         status = EINVAL;
 
2594
         goto exit_free;
 
2595
      }
2528
2596
   }
2529
2597
 
2530
2598
   LOG(4, ("HgfsSetattrFromName: setting attrs for \"%s\"\n", localName));
2647
2715
HgfsInternalStatus
2648
2716
HgfsServerScandir(char const *baseDir,      // IN: Directory to search in
2649
2717
                  size_t baseDirLen,        // IN: Ignored
 
2718
                  Bool followSymlinks,      // IN: followSymlinks config option
2650
2719
                  DirectoryEntry ***dents,  // OUT: Array of DirectoryEntrys
2651
2720
                  int *numDents)            // OUT: Number of DirectoryEntrys
2652
2721
{
2654
2723
   DirectoryEntry **myDents = NULL;
2655
2724
   int myNumDents = 0;
2656
2725
   HgfsInternalStatus status = 0;
 
2726
   int openFlags = O_NONBLOCK | O_RDONLY | O_DIRECTORY | O_NOFOLLOW;
2657
2727
 
2658
2728
   /*
2659
2729
    * XXX: glibc uses 8192 (BUFSIZ) when it can't get st_blksize from a stat.
2661
2731
    */
2662
2732
   char buffer[8192];
2663
2733
 
2664
 
   /* We want a directory. No FIFOs and no symlinks. */
2665
 
   result = Posix_Open(baseDir, O_NONBLOCK | O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
 
2734
   /* Follow symlinks if config option is set. */
 
2735
   if (followSymlinks) {
 
2736
      openFlags &= ~O_NOFOLLOW;
 
2737
   }
 
2738
 
 
2739
   /* We want a directory. No FIFOs. Symlinks only if config option is set. */
 
2740
   result = Posix_Open(baseDir, openFlags);
2666
2741
   if (result < 0) {
2667
2742
      status = errno;
2668
2743
      LOG(4, ("HgfsServerScandir: error in open: %d (%s)\n", status,
2817
2892
   HgfsFileOpenInfo openInfo;
2818
2893
   char *localName = NULL;
2819
2894
   HgfsServerLock serverLock = HGFS_LOCK_NONE;
 
2895
   HgfsShareOptions configOptions;
 
2896
   int followSymlinks;
2820
2897
 
2821
2898
   ASSERT(packetSize);
2822
2899
 
2882
2959
      goto exit;
2883
2960
   }
2884
2961
 
 
2962
   /* Get the config options. */
 
2963
   nameStatus = HgfsServerPolicy_GetShareOptions(openInfo.cpName,
 
2964
                                                 openInfo.cpNameSize,
 
2965
                                                 &configOptions);
 
2966
   if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
 
2967
      LOG(4, ("HgfsServerSearchRead: no matching share: %s.\n", openInfo.cpName));
 
2968
      status = ENOENT;
 
2969
      goto exit;
 
2970
   }
 
2971
 
 
2972
   followSymlinks = HgfsServerPolicy_IsShareOptionSet(configOptions,
 
2973
                                                      HGFS_SHARE_FOLLOW_SYMLINKS);
 
2974
 
2885
2975
   /* See if the name is valid, and if so add it and return the handle. */
2886
 
   status = HgfsValidateOpen(&openInfo, &localId, &newFd);
 
2976
   status = HgfsValidateOpen(&openInfo, followSymlinks, &localId, &newFd);
2887
2977
   if (status == 0) {
2888
2978
      ASSERT(newFd >= 0);
2889
2979
 
3318
3408
                                    &baseDirLen);
3319
3409
   switch (nameStatus) {
3320
3410
   case HGFS_NAME_STATUS_COMPLETE:
 
3411
   {
 
3412
      char const *inEnd;
 
3413
      char *next;
 
3414
      int len;
 
3415
 
3321
3416
      ASSERT(baseDir);
3322
 
 
3323
 
      LOG(4, ("HgfsServerSearchOpen: searching in \"%s\"\n", baseDir));
 
3417
      LOG(4, ("HgfsServerSearchOpen: searching in \"%s\", %s.\n", baseDir, dirName));
 
3418
 
 
3419
      inEnd = dirName + dirNameLength;
 
3420
 
 
3421
      /* Get the first component. */
 
3422
      len = CPName_GetComponentGeneric(dirName, inEnd, "", (char const **) &next);
 
3423
      if (len < 0) {
 
3424
         LOG(4, ("HgfsServerSearchOpen: get first component failed\n"));
 
3425
         status = ENOENT;
 
3426
         goto exit;
 
3427
      }
 
3428
 
 
3429
      LOG(4, ("HgfsServerSearchOpen: dirName: %s.\n", dirName));
3324
3430
      status = HgfsServerSearchRealDir(baseDir,
3325
3431
                                       baseDirLen,
3326
3432
                                       DIRECTORY_SEARCH_TYPE_DIR,
 
3433
                                       dirName,
3327
3434
                                       &handle);
3328
3435
      free(baseDir);
3329
3436
      if (status != 0) {
3331
3438
         goto exit;
3332
3439
      }
3333
3440
      break;
 
3441
   }
3334
3442
 
3335
3443
   case HGFS_NAME_STATUS_INCOMPLETE_BASE:
3336
3444
      /*
3399
3507
   HgfsHandle hgfsSearchHandle;
3400
3508
   DirectoryEntry *dent;
3401
3509
   HgfsSearch search;
 
3510
   HgfsShareOptions configOptions = 0;
3402
3511
 
3403
3512
   ASSERT(packetSize);
3404
3513
 
3419
3528
      return EBADF;
3420
3529
   }
3421
3530
 
 
3531
   /* Get the config options. */
 
3532
   if (search.utf8ShareNameLen != 0) {
 
3533
      nameStatus = HgfsServerPolicy_GetShareOptions(search.utf8ShareName,
 
3534
                                                    search.utf8ShareNameLen,
 
3535
                                                    &configOptions);
 
3536
      if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
 
3537
         LOG(4, ("HgfsServerSearchRead: no matching share: %s.\n", search.utf8ShareName));
 
3538
         free(search.utf8Dir);
 
3539
         free(search.utf8ShareName);
 
3540
         return ENOENT;
 
3541
      }
 
3542
   }
 
3543
 
3422
3544
   while ((dent = HgfsGetSearchResult(hgfsSearchHandle,
3423
3545
                                      requestedOffset, FALSE)) != NULL) {
3424
3546
      unsigned int length;
3426
3548
      char *sharePath;
3427
3549
      size_t sharePathLen;
3428
3550
      size_t fullNameLen;
 
3551
      size_t entryNameLen;
 
3552
      char *entryName = NULL;
 
3553
      Bool freeEntryName = FALSE;
3429
3554
 
3430
3555
      length = strlen(dent->d_name);
3431
3556
 
3443
3568
            LOG(4, ("HgfsServerSearchRead: could not allocate space for "
3444
3569
                    "\"%s\\%s\"\n", search.utf8Dir, dent->d_name));
3445
3570
            free(search.utf8Dir);
 
3571
            free(search.utf8ShareName);
3446
3572
            free(dent);
3447
3573
            return ENOMEM;
3448
3574
         }
3451
3577
         memcpy(&fullName[search.utf8DirLen + 1], dent->d_name, length + 1);
3452
3578
 
3453
3579
         LOG(4, ("HgfsServerSearchRead: about to stat \"%s\"\n", fullName));
3454
 
         status = HgfsGetattrFromName(fullName, &attr, NULL);
 
3580
 
 
3581
         status = HgfsGetattrFromName(fullName, configOptions, &attr, NULL);
3455
3582
         free(fullName);
3456
3583
 
3457
3584
         if (status != 0) {
3460
3587
            free(dent);
3461
3588
            continue;
3462
3589
         }
 
3590
 
 
3591
#if defined(__APPLE__)
 
3592
         /*
 
3593
          * HGFS clients receive names in unicode normal form C,
 
3594
          * (precomposed) so Mac hosts must convert from normal form D
 
3595
          * (decomposed).
 
3596
          */
 
3597
         if (!CodeSet_Utf8FormDToUtf8FormC((const char *)dent->d_name,
 
3598
                                           length,
 
3599
                                           &entryName,
 
3600
                                           &entryNameLen)) {
 
3601
            LOG(4, ("HgfsServerSearchRead: Unable to normalize form C \"%s\"\n",
 
3602
                    dent->d_name));
 
3603
            /* Skip this entry and continue. */
 
3604
            free(dent);
 
3605
            continue;
 
3606
         }
 
3607
 
 
3608
         freeEntryName = TRUE;
 
3609
#else /* defined(__APPLE__) */
 
3610
         entryName = dent->d_name;
 
3611
         entryNameLen = length;
 
3612
#endif /* defined(__APPLE__) */
3463
3613
         break;
3464
3614
      case DIRECTORY_SEARCH_TYPE_BASE:
3465
3615
 
3486
3636
               LOG(4, ("HgfsServerSearchRead: No such share or access denied\n"));
3487
3637
               free(dent);
3488
3638
               free(search.utf8Dir);
 
3639
               free(search.utf8ShareName);
3489
3640
               return HgfsConvertFromNameStatus(nameStatus);
3490
3641
            }
3491
 
            status = HgfsGetattrFromName(sharePath, &attr, NULL);
 
3642
 
 
3643
            status = HgfsGetattrFromName(sharePath, configOptions, &attr, NULL);
3492
3644
            if (status != 0) {
3493
3645
               /*
3494
3646
                * The dent no longer exists. Remove it from the search and get
3501
3653
               continue;
3502
3654
            }
3503
3655
         }
 
3656
 
 
3657
         /*
 
3658
          * No conversion needed on OS X because dent->d_name is the shareName
 
3659
          * that was converted to normal form C in hgfsServerPolicyHost.
 
3660
          */
 
3661
         entryName = dent->d_name;
 
3662
         entryNameLen = length;
3504
3663
         break;
3505
3664
      case DIRECTORY_SEARCH_TYPE_OTHER:
3506
3665
 
3516
3675
      }
3517
3676
 
3518
3677
      free(search.utf8Dir);
3519
 
 
3520
 
      {
3521
 
         size_t entryNameLen;
3522
 
         char *entryName = NULL;
3523
 
         Bool freeEntryName = FALSE;
3524
 
 
3525
 
#if defined(__APPLE__)
3526
 
 
3527
 
         /*
3528
 
          * HGFS clients receive names in unicode normal form C,
3529
 
          * (precomposed) so Mac hosts must convert from normal form D
3530
 
          * (decomposed).
3531
 
          */
3532
 
         if (!CodeSet_Utf8FormDToUtf8FormC((const char *)dent->d_name,
3533
 
                                           length,
3534
 
                                           &entryName,
3535
 
                                           &entryNameLen)) {
3536
 
            LOG(4, ("HgfsServerSearchRead: Unable to normalize form C \"%s\"\n",
3537
 
                    dent->d_name));
3538
 
            /* Skip this entry and continue. */
3539
 
            free(dent);
3540
 
            continue;
3541
 
         }
3542
 
 
3543
 
         freeEntryName = TRUE;
3544
 
#else /* defined(__APPLE__) */
3545
 
         entryName = dent->d_name;
3546
 
         entryNameLen = length;
3547
 
#endif /* defined(__APPLE__) */
3548
 
 
3549
 
         LOG(4, ("HgfsServerSearchRead: dent name is \"%s\" len = %"FMTSZ"u\n",
3550
 
                 entryName, entryNameLen));
3551
 
 
3552
 
         /*
3553
 
          * XXX: HgfsPackSearchReadReply will error out if the dent we
3554
 
          * give it is too large for the packet. Prior to
3555
 
          * HgfsPackSearchReadReply, we'd skip the dent and return the next
3556
 
          * one with success. Now we return an error. This may be a non-issue
3557
 
          * since what filesystems allow dent lengths as high as 6144 bytes?
3558
 
          */
3559
 
         status = HgfsPackSearchReadReply(entryName, entryNameLen, &attr,
3560
 
                                          packetOut, packetSize) ? 0 : EPROTO;
3561
 
 
3562
 
         if (freeEntryName) {
3563
 
            free(entryName);
3564
 
         }
 
3678
      free(search.utf8ShareName);
 
3679
 
 
3680
      LOG(4, ("HgfsServerSearchRead: dent name is \"%s\" len = %"FMTSZ"u\n",
 
3681
              entryName, entryNameLen));
 
3682
 
 
3683
      /*
 
3684
       * XXX: HgfsPackSearchReadReply will error out if the dent we
 
3685
       * give it is too large for the packet. Prior to
 
3686
       * HgfsPackSearchReadReply, we'd skip the dent and return the next
 
3687
       * one with success. Now we return an error. This may be a non-issue
 
3688
       * since what filesystems allow dent lengths as high as 6144 bytes?
 
3689
       */
 
3690
      status = HgfsPackSearchReadReply(entryName, entryNameLen, &attr,
 
3691
                                       packetOut, packetSize) ? 0 : EPROTO;
 
3692
 
 
3693
      if (freeEntryName) {
 
3694
         free(entryName);
3565
3695
      }
3566
3696
 
3567
3697
      free(dent);
3570
3700
 
3571
3701
   /* No entry at this offset */
3572
3702
   free(search.utf8Dir);
 
3703
   free(search.utf8ShareName);
3573
3704
   LOG(4, ("HgfsServerSearchRead: no entry\n"));
3574
3705
   return HgfsPackSearchReadReply(NULL, 0, &attr, packetOut, packetSize) ?
3575
3706
             0 :
3610
3741
   uint32 targetNameLen;
3611
3742
   HgfsHandle file = HGFS_INVALID_HANDLE; /* file handle from driver */
3612
3743
   uint32 caseFlags = 0;
 
3744
   HgfsShareOptions configOptions;
3613
3745
 
3614
3746
   ASSERT(packetSize);
3615
3747
 
3648
3780
                                       caseFlags,
3649
3781
                                       &localName,
3650
3782
                                       NULL);
 
3783
 
3651
3784
      switch (nameStatus) {
3652
3785
      case HGFS_NAME_STATUS_INCOMPLETE_BASE:
3653
3786
         /*
3662
3795
         /* This is a regular lookup; proceed as usual */
3663
3796
         ASSERT(localName);
3664
3797
 
3665
 
         status = HgfsGetattrFromName(localName, &attr, &targetName);
 
3798
         /* Get the config options. */
 
3799
         nameStatus = HgfsServerPolicy_GetShareOptions(cpName, cpNameSize,
 
3800
                                                       &configOptions);
 
3801
         if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
 
3802
            LOG(4, ("HgfsServerGetattr: no matching share: %s.\n", cpName));
 
3803
            free(localName);
 
3804
            status = ENOENT;
 
3805
            goto exit;
 
3806
         }
 
3807
 
 
3808
         status = HgfsGetattrFromName(localName, configOptions, &attr, &targetName);
3666
3809
         free(localName);
3667
3810
         if (status != 0) {
3668
3811
            goto exit;
3737
3880
                                   hints,
3738
3881
                                   caseFlags);
3739
3882
   }
3740
 
   if (!HgfsPackSetattrReply(packetOut, packetSize)) {
 
3883
   if (!HgfsPackSetattrReply(((HgfsRequest *)packetIn)->op,
 
3884
                             packetOut,
 
3885
                             packetSize)) {
3741
3886
      status = EPROTO;
3742
3887
   }
3743
3888
 
3825
3970
      LOG(4, ("HgfsServerCreateDir: error: %s\n", strerror(error)));
3826
3971
      return error;
3827
3972
   }
3828
 
   return HgfsPackCreateDirReply(packetOut, packetSize) ? 0 : EPROTO;
 
3973
   return HgfsPackCreateDirReply(((HgfsRequest *)packetIn)->op,
 
3974
                                 packetOut, packetSize) ?
 
3975
             0 : EPROTO;
3829
3976
}
3830
3977
 
3831
3978
 
3909
4056
      return error;
3910
4057
   }
3911
4058
 
3912
 
   return HgfsPackDeleteReply(packetOut, packetSize) ? 0 : EPROTO;
 
4059
   return HgfsPackDeleteReply(((HgfsRequest *)packetIn)->op,
 
4060
                              packetOut, packetSize) ?
 
4061
             0 : EPROTO;
3913
4062
}
3914
4063
 
3915
4064
 
3999
4148
      return error;
4000
4149
   }
4001
4150
 
4002
 
   return HgfsPackDeleteReply(packetOut, packetSize) ? 0 : EPROTO;
 
4151
   return HgfsPackDeleteReply(((HgfsRequest *)packetIn)->op,
 
4152
                              packetOut, packetSize) ?
 
4153
             0 : EPROTO;
4003
4154
}
4004
4155
 
4005
4156
 
4137
4288
 
4138
4289
   if (hints & HGFS_RENAME_HINT_NO_REPLACE_EXISTING) {
4139
4290
      HgfsFileAttrInfo attr;
 
4291
      HgfsShareOptions configOptions;
 
4292
 
 
4293
      /* Get the config options. */
 
4294
      nameStatus = HgfsServerPolicy_GetShareOptions(cpNewName, cpNewNameLen,
 
4295
                                                    &configOptions);
 
4296
      if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
 
4297
         LOG(4, ("HgfsServerRename: no matching share: %s.\n", cpNewName));
 
4298
         status = ENOENT;
 
4299
         goto exit;
 
4300
      }
4140
4301
 
4141
4302
      /*
4142
4303
       * We were asked to avoid replacing an existing file,
4143
4304
       * so fail if the target exists.
4144
4305
       */
4145
 
      status = HgfsGetattrFromName(localNewName, &attr, NULL);
 
4306
      status = HgfsGetattrFromName(localNewName, configOptions, &attr, NULL);
4146
4307
      if (status == 0) {
4147
4308
         /* The target exists, and so must fail the rename. */
4148
4309
         LOG(4, ("HgfsServerRename: error: target %s exists\n", localNewName));
4168
4329
    * the client to see success anyway, because the rename succeeded.
4169
4330
    */
4170
4331
   HgfsUpdateNodeNames(localOldName, localNewName);
4171
 
   status = HgfsPackRenameReply(packetOut, packetSize) ?
 
4332
   status = HgfsPackRenameReply(((HgfsRequest *)packetIn)->op,
 
4333
                                 packetOut, packetSize) ?
4172
4334
               0 : EPROTO;
4173
4335
 
4174
4336
  exit:
4248
4410
       * Clients should retry using the file name.
4249
4411
       */
4250
4412
      if (requestV3->fileName.flags & HGFS_FILE_NAME_USE_FILE_DESC) {
4251
 
         LOG(4, ("HgfsServerSearchOpen: Doesn't support file handle.\n"));
 
4413
         LOG(4, ("HgfsServerQueryVolume: Doesn't support file handle.\n"));
4252
4414
         return EPARAMETERNOTSUPPORTED;
4253
4415
      }
4254
4416
 
4264
4426
      fileName = requestV3->fileName.name;
4265
4427
      fileNameLength = requestV3->fileName.length;
4266
4428
      *packetSize = HGFS_REP_PAYLOAD_SIZE_V3(replyV3);
4267
 
      LOG(4, ("HgfsServerSearchOpen: HGFS_OP_SEARCH_OPEN_V3\n"));
 
4429
      LOG(4, ("HgfsServerQueryVolume: HGFS_OP_QUERY_VOLUME_INFO_V3\n"));
4268
4430
   } else {
4269
4431
      HgfsRequestQueryVolume *request = (HgfsRequestQueryVolume *)packetIn;
4270
4432
      HgfsReplyQueryVolume *reply = (HgfsReplyQueryVolume *)packetOut;
4484
4646
   uint32 symlinkNameLength;
4485
4647
   char *targetName;
4486
4648
   uint32 targetNameLength;
 
4649
   HgfsShareOptions configOptions;
4487
4650
 
4488
4651
   ASSERT(packetIn);
4489
4652
   ASSERT(packetOut);
4587
4750
 
4588
4751
   /* It is now safe to read the target file name */
4589
4752
 
 
4753
   /* Get the config options. */
 
4754
   nameStatus = HgfsServerPolicy_GetShareOptions(symlinkName, symlinkNameLength,
 
4755
                                                 &configOptions);
 
4756
   if (nameStatus != HGFS_NAME_STATUS_COMPLETE) {
 
4757
      LOG(4, ("HgfsServerSymlinkCreate: no matching share: %s.\n", symlinkName));
 
4758
      return HgfsConvertFromNameStatus(nameStatus);
 
4759
   }
 
4760
 
4590
4761
   /* Convert from CPName-lite to normal and NUL-terminate. */
4591
4762
   memcpy(localTargetName, targetName, targetNameLength);
4592
4763
   CPNameLite_ConvertFrom(localTargetName, targetNameLength, DIRSEPC);
4593
4764
   localTargetName[targetNameLength] = '\0';
4594
4765
 
 
4766
   /* Prohibit symlink ceation if symlink following is enabled. */
 
4767
   if (HgfsServerPolicy_IsShareOptionSet(configOptions, HGFS_SHARE_FOLLOW_SYMLINKS)) {
 
4768
      return EPERM;
 
4769
   }
 
4770
 
4595
4771
   LOG(4, ("HgfsServerSymlinkCreate: creating \"%s\" linked to \"%s\"\n",
4596
4772
           localSymlinkName, localTargetName));
4597
4773