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

« back to all changes in this revision

Viewing changes to lib/hgfsServer/hgfsServerLinux.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
#define _GNU_SOURCE // for O_NOFOLLOW
30
30
 
 
31
#if defined(__APPLE__)
 
32
#define _DARWIN_USE_64_BIT_INODE
 
33
#endif
 
34
 
31
35
#include <stdlib.h>
32
36
#include <stdio.h>
33
37
#include <unistd.h>
95
99
#   include "sig.h"
96
100
#endif
97
101
 
98
 
#if defined(linux) && !defined(GLIBC_VERSION_21)
99
 
/*
100
 
 * Implements the system call (it is not wrapped by glibc 2.1.1)
101
 
 */
102
 
static INLINE int
103
 
_llseek(unsigned int fd,
104
 
        unsigned long offset_high,
105
 
        unsigned long offset_low,
106
 
        loff_t *result,
107
 
        unsigned int whence)
108
 
{
109
 
   return syscall(SYS__llseek, fd, offset_high, offset_low, result, whence);
110
 
}
111
 
#endif
112
 
 
113
102
/*
114
103
 * On Linux, we must wrap getdents64, as glibc does not wrap it for us. We use getdents64
115
104
 * (rather than getdents) because with the latter, we'll get 64-bit offsets and inode
160
149
         dirp[i].d_off = dirp_temp[i].d_off;
161
150
         dirp[i].d_reclen = dirp_temp[i].d_reclen;
162
151
         dirp[i].d_type = DT_UNKNOWN;
 
152
         memset(dirp[i].d_name, 0, sizeof dirp->d_name);
163
153
         memcpy(dirp[i].d_name, dirp_temp[i].d_name,
164
154
                ((sizeof dirp->d_name) < (sizeof dirp_temp->d_name))
165
155
                ? (sizeof dirp->d_name)
171
161
#   endif
172
162
}
173
163
#      define getdents getdents_linux
174
 
#elif defined(__FreeBSD__) || defined(__APPLE__)
 
164
#elif defined(__FreeBSD__)
175
165
#define getdents(fd, dirp, count)                                             \
176
166
({                                                                            \
177
167
   long basep;                                                                \
178
168
   getdirentries(fd, dirp, count, &basep);                                    \
179
169
})
 
170
#elif defined(__APPLE__)
 
171
static INLINE int
 
172
getdents_apple(DIR *fd,               // IN
 
173
               DirectoryEntry *dirp,  // OUT
 
174
               unsigned int count)    // IN: ignored
 
175
{
 
176
   int res = 0;
 
177
   struct dirent *dirEntry;
 
178
   dirEntry = readdir(fd);
 
179
   if (NULL != dirEntry) {
 
180
      memcpy(dirp, dirEntry, dirEntry->d_reclen);
 
181
      res =  dirEntry->d_reclen;
 
182
   }
 
183
   return res;
 
184
}
 
185
#      define getdents getdents_apple
180
186
#endif
181
187
 
182
188
/*
321
327
static HgfsInternalStatus HgfsEffectivePermissions(char *fileName,
322
328
                                                   Bool readOnlyShare,
323
329
                                                   uint32 *permissions);
324
 
#if defined(__APPLE__)
325
 
static void HgfsConvertStat64ToStat(const struct stat64 *stats64,
326
 
                                    struct stat *stats,
327
 
                                    uint64 *creationTime);
328
 
#else
329
330
static uint64 HgfsGetCreationTime(const struct stat *stats);
330
 
#endif
331
331
 
332
332
#ifdef HGFS_OPLOCKS
333
333
/*
748
748
    * file name still refers to the same pair
749
749
    */
750
750
 
 
751
#if defined(__APPLE__)
 
752
   /*
 
753
    *  Can't use Posix_Stat because of inconsistent definition
 
754
    *  of _DARWIN_USE_64_BIT_INODE in this file and in other libraries.
 
755
    */
 
756
   if (stat(localName, &nodeStat) < 0) {
 
757
#else
751
758
   if (Posix_Stat(localName, &nodeStat) < 0) {
 
759
#endif
752
760
      int error = errno;
753
761
 
754
762
      LOG(4, ("%s: couldn't stat local file \"%s\": %s\n", __FUNCTION__,
1907
1915
}
1908
1916
 
1909
1917
 
1910
 
#if defined(__APPLE__)
1911
 
/*
1912
 
 *-----------------------------------------------------------------------------
1913
 
 *
1914
 
 * HgfsConvertStat64ToStat --
1915
 
 *
1916
 
 *    Helper function that converts data in stat64 format into stat format.
1917
 
 *    It returns creationTime in HGFS platform independent format.
1918
 
 *
1919
 
 * Results:
1920
 
 *    None.
1921
 
 *
1922
 
 * Side effects:
1923
 
 *    None
1924
 
 *
1925
 
 *-----------------------------------------------------------------------------
1926
 
 */
1927
 
 
1928
 
static void
1929
 
HgfsConvertStat64ToStat(const struct stat64 *stats64,  // IN: data in stat64 format
1930
 
                        struct stat *stats,            // OUT: data in stat format
1931
 
                        uint64 *creationTime)          // OUT: creation time
1932
 
{
1933
 
   stats->st_dev = stats64->st_dev;
1934
 
   stats->st_ino = stats64->st_ino;
1935
 
   stats->st_mode = stats64->st_mode;
1936
 
   stats->st_nlink = stats64->st_nlink;
1937
 
   stats->st_uid = stats64->st_uid;
1938
 
   stats->st_gid = stats64->st_gid;
1939
 
   stats->st_rdev = stats64->st_rdev;
1940
 
   stats->st_atimespec = stats64->st_atimespec;
1941
 
   stats->st_mtimespec = stats64->st_mtimespec;
1942
 
   stats->st_ctimespec = stats64->st_ctimespec;
1943
 
   stats->st_size = stats64->st_size;
1944
 
   stats->st_blocks = stats64->st_blocks;
1945
 
   stats->st_blksize = stats64->st_blksize;
1946
 
   stats->st_flags = stats64->st_flags;
1947
 
   stats->st_gen = stats64->st_gen;
1948
 
   *creationTime =  HgfsConvertTimeSpecToNtTime(&stats64->st_birthtimespec);
1949
 
}
1950
 
#else
1951
 
 
1952
 
 
1953
1918
/*
1954
1919
 *-----------------------------------------------------------------------------
1955
1920
 *
2008
1973
#   else
2009
1974
   creationTime   = HgfsConvertTimeSpecToNtTime(&stats->st_mtim);
2010
1975
#   endif
 
1976
#elif defined(__APPLE__)
 
1977
   creationTime   = HgfsConvertTimeSpecToNtTime(&stats->st_birthtimespec);
2011
1978
#else
2012
1979
   /*
2013
1980
    * Solaris: No nanosecond timestamps, no file create timestamp.
2016
1983
#endif
2017
1984
   return creationTime;
2018
1985
}
2019
 
#endif
2020
1986
 
2021
1987
 
2022
1988
/*
2024
1990
 *
2025
1991
 * HgfsStat --
2026
1992
 *
2027
 
 *    Wrapper function that invokes stat64 on Mac OS and stat on Linux (where stat64 is
2028
 
 *    unavailable).
 
1993
 *    Wrapper function that invokes stat on Mac OS and on Linux.
 
1994
 *
2029
1995
 *    Returns filled stat structure and a file creation time. File creation time is
2030
1996
 *    the birthday time for Mac OS and last write time for Linux (which does not support
2031
1997
 *    file creation time).
2048
2014
{
2049
2015
   int error;
2050
2016
#if defined(__APPLE__)
2051
 
   struct stat64 stats64;
2052
2017
   if (followLink) {
2053
 
      error = stat64(fileName, &stats64);
 
2018
      error = stat(fileName, stats);
2054
2019
   } else {
2055
 
      error = lstat64(fileName, &stats64);
2056
 
   }
2057
 
   if (error == 0) {
2058
 
      HgfsConvertStat64ToStat(&stats64, stats, creationTime);
 
2020
      error = lstat(fileName, stats);
2059
2021
   }
2060
2022
#else
2061
2023
   if (followLink) {
2063
2025
   } else {
2064
2026
      error = Posix_Lstat(fileName, stats);
2065
2027
   }
 
2028
#endif
2066
2029
   *creationTime = HgfsGetCreationTime(stats);
2067
 
#endif
2068
2030
   return error;
2069
2031
}
2070
2032
 
2074
2036
 *
2075
2037
 * HgfsFStat --
2076
2038
 *
2077
 
 *    Wrapper function that invokes stat64 on Mac OS and stat on Linux (where stat64 is
2078
 
 *    unavailable).
 
2039
 *    Wrapper function that invokes fstat.
 
2040
 *
2079
2041
 *    Returns filled stat structure and a file creation time. File creation time is
2080
2042
 *    the birthday time for Mac OS and last write time for Linux (which does not support
2081
2043
 *    file creation time).
2096
2058
          uint64 *creationTime)   // OUT: file creation time
2097
2059
{
2098
2060
   int error = 0;
2099
 
#if defined(__APPLE__)
2100
 
   struct stat64 stats64;
2101
 
   error = fstat64(fd, &stats64);
2102
 
   if (error == 0) {
2103
 
      HgfsConvertStat64ToStat(&stats64, stats, creationTime);
2104
 
   }
2105
 
#else
2106
2061
   if (fstat(fd, stats) < 0) {
2107
2062
      error = errno;
2108
2063
   }
2109
2064
   *creationTime = HgfsGetCreationTime(stats);
2110
 
#endif
2111
2065
   return error;
2112
2066
}
2113
2067
 
3139
3093
 
3140
3094
   return result;
3141
3095
#else
3142
 
   /* NOOP on Linux where the name is already has the correct encoding. */
3143
 
   return TRUE;
 
3096
   size_t size;
 
3097
   /*
 
3098
    * Buffer may contain invalid data after the null terminating character.
 
3099
    * We need to check the validity of the buffer only till the null
 
3100
    * terminating character (if any). Calculate the real size of the
 
3101
    * string before calling Unicode_IsBufferValid().
 
3102
    */
 
3103
   for (size = 0; size < bufferSize ; size++) {
 
3104
      if ('\0' == buffer[size]) {
 
3105
         break;
 
3106
      }
 
3107
   }
 
3108
 
 
3109
   return Unicode_IsBufferValid(buffer, size, STRING_ENCODING_UTF8);
3144
3110
#endif /* defined(__APPLE__) */
3145
3111
}
3146
3112
 
3156
3122
 *    symlinks. Instead, we'll open(2) the directory with O_DIRECTORY and
3157
3123
 *    O_NOFOLLOW, call getdents(2) directly, then close(2) the directory.
3158
3124
 *
 
3125
 *    On Mac OS getdirentries became deprecated starting from 10.6 and
 
3126
 *    there is no similar API available. Thus on Mac OS readdir is used that
 
3127
 *    returns one directory entry at a time.
 
3128
 *
3159
3129
 * Results:
3160
3130
 *    Zero on success. numDents contains the number of directory entries found.
3161
3131
 *    Non-zero on error.
3173
3143
                  DirectoryEntry ***dents,  // OUT: Array of DirectoryEntrys
3174
3144
                  int *numDents)            // OUT: Number of DirectoryEntrys
3175
3145
{
3176
 
   int fd = -1, result;
 
3146
#if defined(__APPLE__)
 
3147
   DIR *fd = NULL;
 
3148
#else
 
3149
   int fd = -1;
 
3150
   int openFlags = O_NONBLOCK | O_RDONLY | O_DIRECTORY | O_NOFOLLOW;
 
3151
#endif
 
3152
   int result;
3177
3153
   DirectoryEntry **myDents = NULL;
3178
3154
   int myNumDents = 0;
3179
3155
   HgfsInternalStatus status = 0;
3180
 
   int openFlags = O_NONBLOCK | O_RDONLY | O_DIRECTORY | O_NOFOLLOW;
3181
3156
 
3182
3157
   /*
3183
3158
    * XXX: glibc uses 8192 (BUFSIZ) when it can't get st_blksize from a stat.
3185
3160
    */
3186
3161
   char buffer[8192];
3187
3162
 
 
3163
#if defined(__APPLE__)
 
3164
   /*
 
3165
    * Since opendir does not support O_NOFOLLOW flag need to explicitly verify
 
3166
    * that we are not dealing with symlink if follow symlinks is
 
3167
    * not allowed.
 
3168
    */
 
3169
   if (!followSymlinks) {
 
3170
      struct stat st;
 
3171
      if (lstat(baseDir, &st) == -1) {
 
3172
         status = errno;
 
3173
         LOG(4, ("%s: error in lstat: %d (%s)\n", __FUNCTION__, status,
 
3174
                 strerror(status)));
 
3175
         goto exit;
 
3176
      }
 
3177
      if (S_ISLNK(st.st_mode)) {
 
3178
         status = EACCES;
 
3179
         LOG(4, ("%s: do not follow symlink\n", __FUNCTION__));
 
3180
         goto exit;
 
3181
      }
 
3182
   }
 
3183
   fd = Posix_OpenDir(baseDir);
 
3184
   if (NULL ==  fd) {
 
3185
      status = errno;
 
3186
      LOG(4, ("%s: error in opendir: %d (%s)\n", __FUNCTION__, status,
 
3187
              strerror(status)));
 
3188
      goto exit;
 
3189
   }
 
3190
#else
3188
3191
   /* Follow symlinks if config option is set. */
3189
3192
   if (followSymlinks) {
3190
3193
      openFlags &= ~O_NOFOLLOW;
3199
3202
      goto exit;
3200
3203
   }
3201
3204
   fd = result;
 
3205
#endif
3202
3206
 
3203
3207
   /*
3204
3208
    * Rather than read a single dent at a time, batch up multiple dents
3262
3266
   }
3263
3267
 
3264
3268
  exit:
 
3269
#if defined(__APPLE__)
 
3270
   if (NULL != fd && closedir(fd) < 0) {
 
3271
#else
3265
3272
   if (fd != -1 && close(fd) < 0) {
 
3273
#endif
3266
3274
      status = errno;
3267
3275
      LOG(4, ("%s: error in close: %d (%s)\n", __FUNCTION__, status,
3268
3276
              strerror(status)));
3377
3385
      return EBADF;
3378
3386
   }
3379
3387
 
3380
 
#if defined(GLIBC_VERSION_21) || defined(__APPLE__)
 
3388
#if defined(__linux__) || defined(__APPLE__)
3381
3389
   /* Read from the file. */
3382
3390
   if (sequentialOpen) {
3383
3391
      error = read(fd, payload, requiredSize);
3480
3488
      return EBADF;
3481
3489
   }
3482
3490
 
3483
 
#if defined(GLIBC_VERSION_21) || defined(__APPLE__)
 
3491
#if defined(__linux__) || defined(__APPLE__)
3484
3492
   /* Write to the file. */
3485
3493
   if (sequentialOpen) {
3486
3494
      error = write(fd, payload, requiredSize);
3887
3895
                   HgfsRenameHint hints)   // IN: rename hints
3888
3896
{
3889
3897
   HgfsInternalStatus status = 0;
3890
 
   int error;
3891
3898
 
3892
3899
   if (hints & HGFS_RENAME_HINT_NO_REPLACE_EXISTING) {
3893
 
      status = HgfsPlatformFileExists(localTargetName);
3894
 
      if (0 == status) {
 
3900
      if (0 == HgfsPlatformFileExists(localTargetName)) {
3895
3901
         status = EEXIST;
3896
 
      }
3897
 
   }
3898
 
 
3899
 
   if (0 == status) {
3900
 
      LOG(4, ("%s: renaming \"%s\" to \"%s\"\n", __FUNCTION__,
3901
 
         localSrcName, localTargetName));
3902
 
      error = Posix_Rename(localSrcName, localTargetName);
3903
 
      if (error) {
3904
 
         status = errno;
3905
 
         LOG(4, ("%s: error: %s\n", __FUNCTION__, strerror(status)));
3906
 
      }
3907
 
   }
 
3902
         goto exit;
 
3903
      }
 
3904
   }
 
3905
 
 
3906
   LOG(4, ("%s: renaming \"%s\" to \"%s\"\n", __FUNCTION__,
 
3907
       localSrcName, localTargetName));
 
3908
   status = Posix_Rename(localSrcName, localTargetName);
 
3909
   if (status) {
 
3910
      status = errno;
 
3911
      LOG(4, ("%s: error: %s\n", __FUNCTION__, strerror(status)));
 
3912
   }
 
3913
 
 
3914
exit:
3908
3915
   return status;
3909
3916
}
3910
3917
 
4401
4408
 *
4402
4409
 * HgfsGetHiddenXAttr --
4403
4410
 *
4404
 
 *    Always returns EINVAL since there is no support for invisible files in Linux
 
4411
 *    Always returns 0 since there is no support for invisible files in Linux
4405
4412
 *    HGFS server.
4406
4413
 *
4407
4414
 * Results:
4408
 
 *    Currently always returns EINVAL.  Will return 0 when support for invisible files
4409
 
 *    is implemented in Linux server.
 
4415
 *    0 always. This is required to allow apps that use the hidden feature to
 
4416
 *    continue to work. attribute value is set to FALSE always.
4410
4417
 *
4411
4418
 * Side effects:
4412
4419
 *    None
4418
4425
HgfsGetHiddenXAttr(char const *fileName,    // IN: File name
4419
4426
                   Bool *attribute)         // OUT: Value of the hidden attribute
4420
4427
{
4421
 
   return EINVAL;
 
4428
   *attribute = FALSE;
 
4429
   return 0;
4422
4430
}
4423
4431
 
4424
4432
 
4428
4436
 * HgfsSetHiddenXAttr --
4429
4437
 *
4430
4438
 *    Sets new value for the invisible attribute of a file.
4431
 
 *    Currently Linux server does not support invisible or hiddden files thus
4432
 
 *    the function fails when a attempt to mark a file as hidden is made.
 
4439
 *    Currently Linux server does not support invisible or hiddden files.
 
4440
 *    So this is a nop.
4433
4441
 *
4434
4442
 * Results:
4435
 
 *    0 if succeeded, error code otherwise.
 
4443
 *    0 always. This is required to allow apps that use the hidden feature to
 
4444
 *    continue to work.
4436
4445
 *
4437
4446
 * Side effects:
4438
4447
 *    None
4444
4453
HgfsSetHiddenXAttr(char const *fileName,   // IN: File name
4445
4454
                   Bool value)             // IN: Value of the attribute to set
4446
4455
{
4447
 
   return value ? EINVAL : 0;
 
4456
   return 0;
4448
4457
}
4449
4458
#endif // __APPLE__