[packages/open-vm-tools] - added build fixes for linux 3.11 and 3.12 fro debian and ubuntu - rel 9

baggins baggins at pld-linux.org
Sat Feb 8 17:47:11 CET 2014


commit 4a655ebc7c145d85c5e01f3b5a5c461de163baa2
Author: Jan Rękorajski <baggins at pld-linux.org>
Date:   Sat Feb 8 17:46:33 2014 +0100

    - added build fixes for linux 3.11 and 3.12 fro debian and ubuntu
    - rel 9

 open-vm-tools-linux-3.11.patch | 874 +++++++++++++++++++++++++++++++++++++++++
 open-vm-tools-linux-3.12.patch | 224 +++++++++++
 open-vm-tools.spec             |   6 +-
 3 files changed, 1103 insertions(+), 1 deletion(-)
---
diff --git a/open-vm-tools.spec b/open-vm-tools.spec
index 90740ef..d684778 100644
--- a/open-vm-tools.spec
+++ b/open-vm-tools.spec
@@ -37,7 +37,7 @@ exit 1
 %define		subver	%(echo %{snap} | tr -d .)
 %define		ver     9.4.0
 %define		rev     1280544
-%define		rel	8
+%define		rel	9
 %define		pname	open-vm-tools
 %define		modsrc	modules/linux
 Summary:	VMWare guest utilities
@@ -57,6 +57,8 @@ Source2:	%{pname}-modprobe.d
 Source3:	%{pname}-init
 Source4:	%{pname}-vmware-user.desktop
 Patch0:		%{pname}-linux-3.10.patch
+Patch1:		%{pname}-linux-3.11.patch
+Patch2:		%{pname}-linux-3.12.patch
 URL:		http://open-vm-tools.sourceforge.net/
 BuildRequires:	rpmbuild(macros) >= 1.679
 %if %{with userspace}
@@ -315,6 +317,8 @@ export OVT_SOURCE_DIR=$PWD\
 %setup -q -n %{pname}-%{ver}-%{rev}
 %if %{with kernel}
 %patch0 -p1
+%patch1 -p1
+%patch2 -p1
 %endif
 
 cp %{SOURCE1} packaging
diff --git a/open-vm-tools-linux-3.11.patch b/open-vm-tools-linux-3.11.patch
new file mode 100644
index 0000000..a4ec7c4
--- /dev/null
+++ b/open-vm-tools-linux-3.11.patch
@@ -0,0 +1,874 @@
+Author: Nate Muench <NowIWillDestroyAbydos at gmail.com>
+Description: Fixes building of vmhgfs module with Linux 3.11
+
+--- a/modules/linux/vmhgfs/inode.c
++++ b/modules/linux/vmhgfs/inode.c
+@@ -31,6 +31,9 @@
+ #include <linux/namei.h>
+ #endif
+ #include <linux/highmem.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
++#include <linux/dcache.h>
++#endif
+ 
+ #include "compat_cred.h"
+ #include "compat_fs.h"
+@@ -1838,7 +1841,11 @@ HgfsPermission(struct inode *inode,
+ #endif
+                            &inode->i_dentry,
+                            d_alias) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
++         int dcount = d_count(dentry);
++#else
+          int dcount = dentry->d_count;
++#endif
+          if (dcount) {
+             LOG(4, ("Found %s %d \n", dentry->d_name.name, dcount));
+             return HgfsAccessInt(dentry, mask & (MAY_READ | MAY_WRITE | MAY_EXEC));
+@@ -1891,10 +1898,12 @@ HgfsPermission(struct inode *inode,
+       list_for_each(pos, &inode->i_dentry) {
+          int dcount;
+          struct dentry *dentry = list_entry(pos, struct dentry, d_alias);
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
+-         dcount = atomic_read(&dentry->d_count);
+-#else
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
++         dcount = d_count(dentry);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+          dcount = dentry->d_count;
++#else
++         dcount = atomic_read(&dentry->d_count);
+ #endif
+          if (dcount) {
+             LOG(4, ("Found %s %d \n", (dentry)->d_name.name, dcount));
+From 4a527c999422eaba9795b18e89b69fbeefda8583 Mon Sep 17 00:00:00 2001
+From: "VMware, Inc" <>
+Date: Tue, 17 Sep 2013 20:36:04 -0700
+Subject: [PATCH] HGFS: Make Linux client compile on kernels 3.11
+
+HgfsReaddir has been replaced with HgfsIterate for the newer releases
+of the kernel 3.11 and newer.
+
+Signed-off-by: Dmitry Torokhov <dtor at vmware.com>
+---
+ open-vm-tools/modules/linux/vmhgfs/dir.c | 718 +++++++++++++++++++++++--------
+ 1 file changed, 538 insertions(+), 180 deletions(-)
+
+diff --git a/modules/linux/vmhgfs/dir.c b/open-vm-tools/modules/linux/vmhgfs/dir.c
+index 1d0351a..e4e82b4 100644
+--- a/modules/linux/vmhgfs/dir.c
++++ b/modules/linux/vmhgfs/dir.c
+@@ -60,13 +60,27 @@ static int HgfsGetNextDirEntry(HgfsSuperInfo *si,
+ static int HgfsPackDirOpenRequest(struct file *file,
+                                   HgfsOp opUsed,
+                                   HgfsReq *req);
++static Bool
++HgfsReaddirFillEntry(filldir_t filldirCb,
++                     void *context,
++                     char *entryName,
++                     uint32 entryNameLength,
++                     loff_t entryPos,
++                     ino_t entryIno,
++                     uint32 entryType);
+ 
+ /* HGFS file operations for directories. */
+ static int HgfsDirOpen(struct inode *inode,
+                        struct file *file);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
++static int HgfsReaddir(struct file *file,
++                       struct dir_context *ctx);
++#else
+ static int HgfsReaddir(struct file *file,
+                        void *dirent,
+                        filldir_t filldir);
++#endif
+ static int HgfsDirRelease(struct inode *inode,
+                           struct file *file);
+ static loff_t HgfsDirLlseek(struct file *file,
+@@ -79,7 +93,11 @@ struct file_operations HgfsDirFileOperations = {
+    .owner       = THIS_MODULE,
+    .open        = HgfsDirOpen,
+    .read        = generic_read_dir,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
++   .iterate     = HgfsReaddir,
++#else
+    .readdir     = HgfsReaddir,
++#endif
+    .release     = HgfsDirRelease,
+ };
+ 
+@@ -794,7 +812,303 @@ HgfsDirOpen(struct inode *inode,  // IN: Inode of the dir to open
+ /*
+  *----------------------------------------------------------------------
+  *
+- * HgfsReaddir --
++ * HgfsReaddirRefreshEntries --
++ *
++ *    refresh the file entries if the handle is stale by reopening.
++ *
++ * Results:
++ *    Zero on success, otherwise failure.
++ *
++ * Side effects:
++ *    None
++ *
++ *----------------------------------------------------------------------
++ */
++
++static int
++HgfsReaddirRefreshEntries(struct file *file)    // IN: File pointer for this open
++{
++   int result = 0;
++
++   /*
++    * rm -rf 6.10+ breaks because it does following:
++    * an 'fd = open()' on a directory, followed by unlinkat()
++    * which removes an entry from the directory it and then
++    * fdopendir(fd). We get a call on open() but not on fdopendir(),
++    * which means that we do not reflect the action of unlinkat(),
++    * and thus rm -rf gets confused and marking entry as unremovable.
++    * Note that this problem exists because hgfsServer reads all
++    * the directory entries at open(). Interested reader may look at
++    * coreutils/src/remove.c file.
++    *
++    * So as a workaround, we ask the server to populate entries on
++    * first readdir() call rather than opendir(). This effect is
++    * achieved by closing and reopening the directory. Grrr!
++    *
++    * XXX We should get rid of this code when/if we remove the above
++    * behavior from hgfsServer.
++    */
++   if (FILE_GET_FI_P(file)->isStale) {
++      result = HgfsPrivateDirReOpen(file);
++   }
++
++   LOG(6, (KERN_DEBUG "VMware hgfs: %s: error: stale handle (%s) return %d)\n",
++            __func__, file->f_dentry->d_name.name, result));
++   return result;
++}
++
++
++/*
++ *----------------------------------------------------------------------
++ *
++ * HgfsGetFileInode --
++ *
++ *    Get file inode from the hgfs attributes or generate from the super block.
++ *
++ * Results:
++ *    The inode entry.
++ *
++ * Side effects:
++ *    None
++ *
++ *----------------------------------------------------------------------
++ */
++
++static ino_t
++HgfsGetFileInode(HgfsAttrInfo const *attr,     // IN: Attrs to use
++                 struct super_block *sb)       // IN: Superblock of this fs
++{
++   ino_t inodeEntry;
++
++   ASSERT(attr);
++   ASSERT(sb);
++
++   if (attr->mask & HGFS_ATTR_VALID_FILEID) {
++      inodeEntry = attr->hostFileId;
++   } else {
++      inodeEntry = iunique(sb, HGFS_RESERVED_INO);
++   }
++
++   LOG(4, (KERN_DEBUG "VMware hgfs: %s: return %lu\n", __func__, inodeEntry));
++   return inodeEntry;
++}
++
++
++/*
++ *----------------------------------------------------------------------
++ *
++ * HgfsGetFileType --
++ *
++ *    Get file type according to the hgfs attributes.
++ *
++ * Results:
++ *    The file type.
++ *
++ * Side effects:
++ *    None
++ *
++ *----------------------------------------------------------------------
++ */
++
++static uint32
++HgfsGetFileType(HgfsAttrInfo const *attr)     // IN: Attrs to use
++{
++   uint32 type;
++
++   ASSERT(attr);
++
++   switch (attr->type) {
++   case HGFS_FILE_TYPE_SYMLINK:
++      type = DT_LNK;
++      break;
++
++   case HGFS_FILE_TYPE_REGULAR:
++      type = DT_REG;
++      break;
++
++   case HGFS_FILE_TYPE_DIRECTORY:
++      type = DT_DIR;
++      break;
++
++   default:
++      /*
++       * XXX Should never happen. I'd put NOT_IMPLEMENTED() here
++       * but if the driver ever goes in the host it's probably not
++       * a good idea for an attacker to be able to hang the host
++       * simply by using a bogus file type in a reply. [bac]
++       *
++       * Well it happens! Refer bug 548177 for details. In short,
++       * when the user deletes a share, we hit this code path.
++       *
++       */
++      type = DT_UNKNOWN;
++      break;
++   }
++
++   LOG(4, (KERN_DEBUG "VMware hgfs: %s: return %d\n", __func__, type));
++   return type;
++}
++
++
++/*
++ *----------------------------------------------------------------------
++ *
++ * HgfsReaddirNextEntry --
++ *
++ *    Called whenever a process opens a directory in our filesystem.
++ *
++ *    We send a "Search Open" request to the server with the name
++ *    stored in this file's inode. If the Open succeeds, we store the
++ *    search handle sent by the server in the file struct so it can be
++ *    accessed by readdir and close.
++ *
++ * Results:
++ *    Returns zero if on success, error on failure.
++ *
++ * Side effects:
++ *    None
++ *
++ *----------------------------------------------------------------------
++ */
++
++static int
++HgfsReaddirNextEntry(struct file *file,              // IN: file
++                     loff_t entryPos,                // IN: position
++                     Bool dotAndDotDotIgnore,        // IN: ignore "." and ".."
++                     size_t entryNameBufLen,         // IN: name buffer length
++                     char *entryName,                // OUT: entry name
++                     uint32 *entryNameLength,        // OUT: max name length
++                     ino_t *entryIno,                // OUT: inode entry number
++                     uint32 *entryType,              // OUT: entry type
++                     Bool *entryIgnore,              // OUT: ignore this entry or not
++                     Bool *entryEnd)                 // OUT: no more entries
++{
++   HgfsSuperInfo *si;
++   HgfsAttrInfo entryAttrs;
++   char *fileName = NULL;
++   int result;
++
++   ASSERT(file->f_dentry->d_inode->i_sb);
++
++   si = HGFS_SB_TO_COMMON(file->f_dentry->d_inode->i_sb);
++   *entryIgnore = FALSE;
++
++   /*
++    * Nonzero result = we failed to get valid reply from server.
++    * Zero result:
++    *     - done == TRUE means we hit the end of the directory
++    *     - Otherwise, fileName has the name of the next dirent
++    *
++    */
++
++   result = HgfsGetNextDirEntry(si,
++                                FILE_GET_FI_P(file)->handle,
++                                (uint32)entryPos,
++                                &entryAttrs,
++                                &fileName,
++                                entryEnd);
++   if (result == -ENAMETOOLONG) {
++      /*
++       * Skip dentry if its name is too long (see below).
++       *
++       * XXX: If a bad server sends us bad packets, we can loop here
++       * forever, as I did while testing *grumble*. Maybe we should error
++       * in that case.
++       */
++      LOG(4, (KERN_DEBUG "VMware hgfs: %s: error getnextdentry name %d\n",
++               __func__, result));
++      *entryIgnore = TRUE;
++      result = 0;
++      goto exit;
++   } else if (result) {
++      /* Error  */
++      LOG(4, (KERN_DEBUG "VMware hgfs: %s: error getnextdentry %d\n",
++               __func__, result));
++      goto exit;
++   }
++
++   if (*entryEnd) {
++      LOG(10, (KERN_DEBUG "VMware hgfs: %s: end of dir reached\n", __func__));
++      goto exit;
++   }
++
++   /*
++    * Escape all non-printable characters (which for linux is just
++    * "/").
++    *
++    * Note that normally we would first need to convert from the
++    * CP name format, but that is done implicitely here since we
++    * are guaranteed to have just one path component per dentry.
++    */
++   result = HgfsEscape_Do(fileName, strlen(fileName),
++                          entryNameBufLen, entryName);
++   kfree(fileName);
++   fileName = NULL;
++
++   /*
++    * Check the filename length.
++    *
++    * If the name is too long to be represented in linux, we simply
++    * skip it (i.e., that file is not visible to our filesystem).
++    *
++    * HgfsEscape_Do returns a negative value if the escaped
++    * output didn't fit in the specified output size, so we can
++    * just check its return value.
++    */
++   if (result < 0) {
++      /*
++       * XXX: Another area where a bad server could cause us to loop
++       * forever.
++       */
++      *entryIgnore = TRUE;
++      result = 0;
++      goto exit;
++   }
++
++   *entryNameLength = result;
++   result = 0;
++
++   /*
++    * It is unfortunate, but the HGFS server sends back '.' and ".."
++    * when we do a SearchRead. In an ideal world, these would be faked
++    * on the client, but it would be a real backwards-compatibility
++    * hassle to change the behavior at this point.
++    *
++    * So instead, we'll take the '.' and ".." and modify their inode
++    * numbers so they match what the client expects.
++    */
++   if (!strncmp(entryName, ".", sizeof ".")) {
++      if (!dotAndDotDotIgnore) {
++         *entryIno = file->f_dentry->d_inode->i_ino;
++      } else {
++         *entryIgnore = TRUE;
++      }
++   } else if (!strncmp(entryName, "..", sizeof "..")) {
++      if (!dotAndDotDotIgnore) {
++         *entryIno = compat_parent_ino(file->f_dentry);
++      } else {
++         *entryIgnore = TRUE;
++      }
++   } else {
++     *entryIno = HgfsGetFileInode(&entryAttrs, file->f_dentry->d_inode->i_sb);
++   }
++
++   if (*entryIgnore) {
++      goto exit;
++   }
++
++   /* Assign the correct dentry type. */
++   *entryType = HgfsGetFileType(&entryAttrs);
++
++exit:
++   return result;
++}
++
++
++/*
++ *----------------------------------------------------------------------
++ *
++ * HgfsDoReaddir --
+  *
+  *    Handle a readdir request. See details below if interested.
+  *
+@@ -820,7 +1134,7 @@ HgfsDirOpen(struct inode *inode,  // IN: Inode of the dir to open
+  *
+  *     - Passing an inum of zero to filldir doesn't work. At a minimum,
+  *       you have to make up a bogus inum for each dentry.
+- *     - Passing the correct d_type to filldir seems to be non-critical;
++ *     - Passing the correct entryType to filldir seems to be non-critical;
+  *       apparently most programs (such as ls) stat each file if they
+  *       really want to know what type it is. However, passing the
+  *       correct type means that ls doesn't bother calling stat on
+@@ -839,24 +1153,20 @@ HgfsDirOpen(struct inode *inode,  // IN: Inode of the dir to open
+  */
+ 
+ static int
+-HgfsReaddir(struct file *file, // IN:  Directory to read from
+-            void *dirent,      // OUT: Buffer to copy dentries into
+-            filldir_t filldir) // IN:  Filler function
++HgfsDoReaddir(struct file *file,         // IN:
++              Bool dotAndDotDotIgnore,   // IN: ignore "." and ".."
++              filldir_t filldirCb,       // IN: system filler callback
++              void *filldirCtx,          // IN/OUT: system filler context
++              loff_t *entryPos)          // IN/OUT: entry position
+ {
+-   HgfsSuperInfo *si;
+-   HgfsAttrInfo attr;
+-   uint32 d_type;    // type of dirent
+-   char *fileName = NULL;
+-   char *escName = NULL; // buf for escaped version of name
+-   size_t escNameLength = NAME_MAX + 1;
+-   int nameLength = 0;
++   char *entryName = NULL; // buf for escaped version of name
++   size_t entryNameBufLen = NAME_MAX + 1;
++   int entryNameLength = 0;
+    int result = 0;
+-   Bool done = FALSE;
+-   Bool isStale = FALSE;
+-   ino_t ino;
++   Bool entryEnd = FALSE;
+ 
+    ASSERT(file);
+-   ASSERT(dirent);
++   ASSERT(filldirCtx);
+ 
+    if (!file ||
+       !(file->f_dentry) ||
+@@ -865,209 +1175,257 @@ HgfsReaddir(struct file *file, // IN:  Directory to read from
+       return -EFAULT;
+    }
+ 
+-   ASSERT(file->f_dentry->d_inode->i_sb);
+-
+-   si = HGFS_SB_TO_COMMON(file->f_dentry->d_inode->i_sb);
+-
+-   LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReaddir: dir with name %s, "
+-           "inum %lu, f_pos %Lu\n",
++   LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s, inum %lu, pos %Lu)\n",
++          __func__,
+           file->f_dentry->d_name.name,
+           file->f_dentry->d_inode->i_ino,
+-          file->f_pos));
++          *entryPos));
+ 
+    /*
+-    * rm -rf 6.10+ breaks because it does following:
+-    * an 'fd = open()' on a directory, followed by unlinkat()
+-    * which removes an entry from the directory it and then
+-    * fdopendir(fd). We get a call on open() but not on fdopendir(),
+-    * which means that we do not reflect the action of unlinkat(),
+-    * and thus rm -rf gets confused and marking entry as unremovable.
+-    * Note that this problem exists because hgfsServer reads all
+-    * the directory entries at open(). Interested reader may look at
+-    * coreutils/src/remove.c file.
+-    *
+-    * So as a workaround, we ask the server to populate entries on
+-    * first readdir() call rather than opendir(). This effect is
+-    * achieved by closing and reopening the directory. Grrr!
+-    *
+-    * XXX We should get rid of this code when/if we remove the above
+-    * behavior from hgfsServer.
++    * Refresh entries if required. See rm -rf 6.10+ breaking issue.
+     */
+-   isStale = FILE_GET_FI_P(file)->isStale;
+-   if (isStale) {
+-      result = HgfsPrivateDirReOpen(file);
+-      if (result) {
+-         return result;
+-      }
++   result = HgfsReaddirRefreshEntries(file);
++   if (result != 0) {
++      return result;
+    }
+ 
++
+    /*
+     * Some day when we're out of things to do we can move this to a slab
+     * allocator.
+     */
+-   escName = kmalloc(escNameLength, GFP_KERNEL);
+-   if (!escName) {
++   entryName = kmalloc(entryNameBufLen, GFP_KERNEL);
++   if (entryName == NULL) {
+       LOG(4, (KERN_DEBUG "VMware hgfs: HgfsReaddir: out of memory allocating "
+               "escaped name buffer\n"));
+-      return  -ENOMEM;
++      return -ENOMEM;
+    }
+ 
+-   while (1) {
+-      /*
+-       * Nonzero result = we failed to get valid reply from server.
+-       * Zero result:
+-       *     - done == TRUE means we hit the end of the directory
+-       *     - Otherwise, fileName has the name of the next dirent
+-       *
+-       */
+-
+-      result = HgfsGetNextDirEntry(si,
+-                                   FILE_GET_FI_P(file)->handle,
+-                                   (uint32)file->f_pos,
+-                                   &attr,
+-                                   &fileName,
+-                                   &done);
+-      if (result == -ENAMETOOLONG) {
+-         /*
+-          * Skip dentry if its name is too long (see below).
+-          *
+-          * XXX: If a bad server sends us bad packets, we can loop here
+-          * forever, as I did while testing *grumble*. Maybe we should error
+-          * in that case.
+-          */
+-         file->f_pos++;
+-         continue;
+-      } else if (result) {
+-         /* Error  */
+-         LOG(4, (KERN_DEBUG "VMware hgfs: HgfsReaddir: error "
+-                 "getting dentry\n"));
+-         kfree(escName);
+-         return result;
+-      }
+-
+-      if (done == TRUE) {
+-         LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReaddir: end of dir reached\n"));
++   while (!entryEnd) {
++      Bool entryIgnore;
++      ino_t entryIno = 0;
++      uint32 entryType = DT_UNKNOWN;
++
++      result = HgfsReaddirNextEntry(file,
++                                    *entryPos,
++                                    dotAndDotDotIgnore,
++                                    entryNameBufLen,
++                                    entryName,
++                                    &entryNameLength,
++                                    &entryIno,
++                                    &entryType,
++                                    &entryIgnore,
++                                    &entryEnd);
++
++      if (result != 0) {
++         /* An error occurred retrieving the entry, so exit. */
+          break;
+       }
+ 
+-      /*
+-       * Escape all non-printable characters (which for linux is just
+-       * "/").
+-       *
+-       * Note that normally we would first need to convert from the
+-       * CP name format, but that is done implicitely here since we
+-       * are guaranteed to have just one path component per dentry.
+-       */
+-      result = HgfsEscape_Do(fileName, strlen(fileName),
+-                             escNameLength, escName);
+-      kfree(fileName);
+-      fileName = NULL;
+-
+-      /*
+-       * Check the filename length.
+-       *
+-       * If the name is too long to be represented in linux, we simply
+-       * skip it (i.e., that file is not visible to our filesystem) by
+-       * incrementing file->f_pos and repeating the loop to get the
+-       * next dentry.
+-       *
+-       * HgfsEscape_Do returns a negative value if the escaped
+-       * output didn't fit in the specified output size, so we can
+-       * just check its return value.
+-       */
+-      if (result < 0) {
+-         /*
+-          * XXX: Another area where a bad server could cause us to loop
+-          * forever.
+-          */
+-         file->f_pos++;
++      if (entryEnd) {
++         LOG(10, (KERN_DEBUG "VMware hgfs: %s: end of dir reached\n", __func__));
+          continue;
+       }
+ 
+-      nameLength = result;
+-
+-      /* Assign the correct dentry type. */
+-      switch (attr.type) {
+-
+-      case HGFS_FILE_TYPE_SYMLINK:
+-         d_type = DT_LNK;
+-         break;
+-
+-      case HGFS_FILE_TYPE_REGULAR:
+-         d_type = DT_REG;
+-         break;
+-
+-      case HGFS_FILE_TYPE_DIRECTORY:
+-         d_type = DT_DIR;
+-         break;
+-
+-      default:
+-         /*
+-          * XXX Should never happen. I'd put NOT_IMPLEMENTED() here
+-          * but if the driver ever goes in the host it's probably not
+-          * a good idea for an attacker to be able to hang the host
+-          * simply by using a bogus file type in a reply. [bac]
+-	  *
+-	  * Well it happens! Refer bug 548177 for details. In short,
+-	  * when the user deletes a share, we hit this code path.
+-	  *
+-	  */
+-         d_type = DT_UNKNOWN;
+-         break;
+-      }
+-
+-      /*
+-       * It is unfortunate, but the HGFS server sends back '.' and ".."
+-       * when we do a SearchRead. In an ideal world, these would be faked
+-       * on the client, but it would be a real backwards-compatibility
+-       * hassle to change the behavior at this point.
+-       *
+-       * So instead, we'll take the '.' and ".." and modify their inode
+-       * numbers so they match what the client expects.
+-       */
+-      if (!strncmp(escName, ".", sizeof ".")) {
+-         ino = file->f_dentry->d_inode->i_ino;
+-      } else if (!strncmp(escName, "..", sizeof "..")) {
+-         ino = compat_parent_ino(file->f_dentry);
+-      } else {
+-         if (attr.mask & HGFS_ATTR_VALID_FILEID) {
+-            ino = attr.hostFileId;
+-         } else {
+-            ino = iunique(file->f_dentry->d_inode->i_sb,
+-                          HGFS_RESERVED_INO);
+-         }
++      if (entryIgnore) {
++         *entryPos += 1;
++         continue;
+       }
+ 
+       /*
+-       * Call filldir for this dentry.
++       * Call the HGFS wrapper to the system fill function to set this dentry.
+        */
+-      LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReaddir: calling filldir "
+-              "with \"%s\", %u, %Lu\n", escName, nameLength, file->f_pos));
+-      result = filldir(dirent,         /* filldir callback struct */
+-                       escName,        /* name of dirent */
+-                       nameLength,     /* length of name */
+-                       file->f_pos,    /* offset of dirent */
+-                       ino,            /* inode number (0 makes it not show) */
+-                       d_type);        /* type of dirent */
+-      if (result) {
++      LOG(6, (KERN_DEBUG "VMware hgfs: %s: dir_emit(%s, %u, %Lu)\n",
++              __func__, entryName, entryNameLength, *entryPos));
++      if (!HgfsReaddirFillEntry(filldirCb,        /* filldir callback function */
++                                filldirCtx,       /* filldir callback struct */
++                                entryName,        /* name of dirent */
++                                entryNameLength,  /* length of name */
++                                *entryPos,        /* entry position */
++                                entryIno,         /* inode number (0 makes it not show) */
++                                entryType)) {     /* type of dirent */
+          /*
+-          * This means that filldir ran out of room in the user buffer
++          * This means that dir_emit ran out of room in the user buffer
+           * it was copying into; we just break out and return, but
+           * don't increment f_pos. So the next time the user calls
+           * getdents, this dentry will be requested again, will get
+           * retrieved again, and get copied properly to the user.
+           */
++         result = 0;
+          break;
+       }
+-      file->f_pos++;
++      *entryPos += 1;
+    }
+ 
+-   LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReaddir: finished\n"));
+-   kfree(escName);
++   LOG(6, (KERN_DEBUG "VMware hgfs: %s: return\n",__func__));
++   kfree(entryName);
+    return 0;
+ }
+ 
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
++/*
++ *----------------------------------------------------------------------
++ *
++ * HgfsReaddir --
++ *
++ *    Handle a readdir request.
++ *
++ * Results:
++ *    Returns zero on success, or an error on failure.
++ *
++ * Side effects:
++ *    None
++ *
++ *----------------------------------------------------------------------
++ */
++
++static int
++HgfsReaddir(struct file *file,         // IN:
++            struct dir_context *ctx)   // IN:
++{
++   /* If either dot and dotdot are filled in for us we can exit. */
++   if (!dir_emit_dots(file, ctx)) {
++      LOG(6, (KERN_DEBUG "VMware hgfs: %s: dir_emit_dots(%s, @ %Lu)\n",
++              __func__, file->f_dentry->d_name.name, ctx->pos));
++      return 0;
++   }
++
++   /* It is sufficient to pass the context as it contains the filler function. */
++   return HgfsDoReaddir(file, TRUE, NULL, ctx, &ctx->pos);
++}
++
++
++/*
++ *----------------------------------------------------------------------
++ *
++ * HgfsReaddirFillEntry --
++ *
++ *    Fill a readdir entry.
++ *
++ *    Failure means that fill ran out of room in the user buffer
++ *    it was copying into.
++ *
++ * Results:
++ *    Returns TRUE on success, or FALSE on failure.
++ *
++ * Side effects:
++ *    None
++ *
++ *----------------------------------------------------------------------
++ */
++
++static Bool
++HgfsReaddirFillEntry(filldir_t filldirCb,            // IN: System filler callback
++                     void *filldirCtx,               // IN/OUT: System filler context
++                     char *entryName,                // IN: entry name
++                     uint32 entryNameLength,         // IN: max name length
++                     loff_t entryPos,                // IN: position = (ctx-pos)
++                     ino_t entryIno,                 // IN: inode entry number
++                     uint32 entryType)               // IN: entry type
++{
++   struct dir_context *ctx = filldirCtx;
++   Bool result;
++
++   ASSERT(filldirCb == NULL);   /* Contained within the context structure. */
++   ASSERT(ctx != NULL);
++   ASSERT(ctx->pos == entryPos);
++   ASSERT(entryName != NULL);
++   ASSERT(entryNameLength != 0);
++
++   LOG(6, (KERN_DEBUG "VMware hgfs: %s: dir_emit(%s, %u, %Lu)\n",
++            __func__, entryName, entryNameLength, ctx->pos));
++
++   result = dir_emit(ctx,              /* filldir callback struct */
++                     entryName,        /* name of dirent */
++                     entryNameLength,  /* length of name */
++                     entryIno,         /* inode number (0 makes it not show) */
++                     entryType);       /* type of dirent */
++   return result;
++}
++#else
++
++
++/*
++ *----------------------------------------------------------------------
++ *
++ * HgfsReaddir --
++ *
++ *    Handle a readdir request.
++ *
++ * Results:
++ *    Returns zero on success, or an error on failure.
++ *
++ * Side effects:
++ *    None
++ *
++ *----------------------------------------------------------------------
++ */
++
++static int
++HgfsReaddir(struct file *file, // IN:  Directory to read from
++            void *dirent,      // OUT: Buffer to copy dentries into
++            filldir_t filldir) // IN:  Filler function
++{
++   return HgfsDoReaddir(file, FALSE, filldir, dirent, &file->f_pos);
++}
++
++
++/*
++ *----------------------------------------------------------------------
++ *
++ * HgfsReaddirFillEntry --
++ *
++ *    Fill a readdir entry.
++ *
++ *    Failure means that fill ran out of room in the user buffer
++ *    it was copying into.
++ *
++ * Results:
++ *    Returns TRUE on success, or FALSE on failure.
++ *
++ * Side effects:
++ *    None
++ *
++ *----------------------------------------------------------------------
++ */
++
++static Bool
++HgfsReaddirFillEntry(filldir_t filldirCb,            // IN: System filler callback
++                     void *filldirCtx,               // IN/OUT: System filler context
++                     char *entryName,                // IN: entry name
++                     uint32 entryNameLength,         // IN: max name length
++                     loff_t entryPos,                // IN: position
++                     ino_t entryIno,                 // IN: inode entry number
++                     uint32 entryType)               // IN: entry type
++{
++   Bool result = TRUE;
++   int fillResult;
++
++   ASSERT(filldirCb != NULL);
++   ASSERT(filldirCtx != NULL);
++   ASSERT(entryName != NULL);
++   ASSERT(entryNameLength != 0);
++
++   LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling filldir(%s, %u, %Lu\n",
++           __func__, entryName, entryNameLength, entryPos));
++
++   fillResult = filldirCb(filldirCtx,       /* filldir callback struct */
++                          entryName,        /* name of dirent */
++                          entryNameLength,  /* length of name */
++                          entryPos,         /* offset of dirent */
++                          entryIno,         /* inode number (0 makes it not show) */
++                          entryType);       /* type of dirent */
++
++   if (fillResult != 0) {
++      result = FALSE;
++   }
++   LOG(6, (KERN_DEBUG "VMware hgfs: %s: return %d\n", __func__, result));
++   return result;
++}
++#endif
++
++
+ /*
+  *----------------------------------------------------------------------
+  *
+-- 
+1.8.4.rc3
+
diff --git a/open-vm-tools-linux-3.12.patch b/open-vm-tools-linux-3.12.patch
new file mode 100644
index 0000000..5f2815e
--- /dev/null
+++ b/open-vm-tools-linux-3.12.patch
@@ -0,0 +1,224 @@
+--- open-vm-tools.sept-update.orig/modules/linux/vmblock/linux/file.c	2013-10-05 16:02:32.361985782 -0500
++++ open-vm-tools.sept-update/modules/linux/vmblock/linux/file.c	2013-10-05 16:02:32.357988581 -0500
+@@ -38,6 +38,7 @@
+ typedef ino_t inode_num_t;
+ #endif
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
+ /* Specifically for our filldir_t callback */
+ typedef struct FilldirInfo {
+    filldir_t filldir;
+@@ -76,6 +77,7 @@
+ }
+ 
+ 
++#endif
+ /* File operations */
+ 
+ /*
+@@ -166,11 +126,17 @@
+ 
+ static int
+ FileOpReaddir(struct file *file,  // IN
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
+               void *dirent,       // IN
+               filldir_t filldir)  // IN
++#else
++              struct dir_context *ctx)  // IN
++#endif
+ {
+    int ret;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
+    FilldirInfo info;
++#endif
+    struct file *actualFile;
+ 
+    if (!file) {
+@@ -184,12 +143,19 @@
+       return -EINVAL;
+    }
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
+    info.filldir = filldir;
+    info.dirent = dirent;
+ 
+    actualFile->f_pos = file->f_pos;
+    ret = vfs_readdir(actualFile, Filldir, &info);
+    file->f_pos = actualFile->f_pos;
++#else
++   /* Ricky Wong Yung Fei:
++    * Manipulation of pos is now handled internally by iterate_dir().
++    */
++   ret = iterate_dir(actualFile, ctx);
++#endif
+ 
+    return ret;
+ }
+@@ -237,7 +194,11 @@
+ 
+ 
+ struct file_operations RootFileOps = {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
+    .readdir = FileOpReaddir,
++#else
++   .iterate = FileOpReaddir,
++#endif
+    .open    = FileOpOpen,
+    .release = FileOpRelease,
+ };
+--- open-vm-tools-9.4.0-1280544/modules/linux/vmblock/linux/inode.c~	2014-02-08 12:40:26.486505188 +0100
++++ open-vm-tools-9.4.0-1280544/modules/linux/vmblock/linux/inode.c	2014-02-08 17:15:30.956987114 +0100
+@@ -230,7 +230,12 @@
+       goto out;
+    }
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
++   nd_set_link(nd, iinfo->name);
++   ret = 0;
++#else
+    ret = vfs_follow_link(nd, iinfo->name);
++#endif
+ 
+ out:
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
+--- open-vm-tools-9.4.0-1280544/modules/linux/vmhgfs/link.c~	2013-09-23 17:51:10.000000000 +0200
++++ open-vm-tools-9.4.0-1280544/modules/linux/vmhgfs/link.c	2014-02-08 17:17:37.996986192 +0100
+@@ -111,8 +111,14 @@
+          error = -EINVAL;
+       } else {
+          LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: calling "
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
++                 "nd_set_link\n"));
++         nd_set_link(nd, fileName);
++	 error = 0;
++#else
+                  "vfs_follow_link\n"));
+          error = vfs_follow_link(nd, fileName);
++#endif
+       }
+       kfree(fileName);
+    }
+--- a/modules/linux/vsock/linux/af_vsock.c
++++ b/modules/linux/vsock/linux/af_vsock.c
+@@ -3147,7 +3147,7 @@ __VSockVmciCreate(struct net *net,
+       vsk->connectTimeout = psk->connectTimeout;
+    } else {
+       vsk->trusted = capable(CAP_NET_ADMIN);
+-      vsk->owner = current_uid();
++      vsk->owner = from_kuid(&init_user_ns, current_uid());
+       vsk->queuePairSize = VSOCK_DEFAULT_QP_SIZE;
+       vsk->queuePairMinSize = VSOCK_DEFAULT_QP_SIZE_MIN;
+       vsk->queuePairMaxSize = VSOCK_DEFAULT_QP_SIZE_MAX;
+--- a/modules/linux/vmhgfs/file.c
++++ b/modules/linux/vmhgfs/file.c
+@@ -656,7 +656,8 @@ HgfsOpen(struct inode *inode,  // IN: In
+             iparent = dparent->d_inode;
+ 
+             HgfsSetUidGid(iparent, file->f_dentry,
+-                          current_fsuid(), current_fsgid());
++                          from_kuid(&init_user_ns, current_fsuid()),
++                          from_kgid(&init_user_ns,current_fsgid()));
+ 
+             dput(dparent);
+          }
+--- a/modules/linux/vmhgfs/filesystem.c
++++ b/modules/linux/vmhgfs/filesystem.c
+@@ -231,13 +231,13 @@ HgfsInitSuperInfo(HgfsMountInfo *mountIn
+    if (si->uidSet) {
+       si->uid = mountInfo->uid;
+    } else {
+-      si->uid = current_uid();
++      si->uid = from_kuid(&init_user_ns, current_uid());
+    }
+    si->gidSet = mountInfo->gidSet;
+    if (si->gidSet) {
+       si->gid = mountInfo->gid;
+    } else {
+-      si->gid = current_gid();
++      si->gid = from_kgid(&init_user_ns, current_gid());
+    }
+    si->fmask = mountInfo->fmask;
+    si->dmask = mountInfo->dmask;
+--- a/modules/linux/vmhgfs/inode.c
++++ b/modules/linux/vmhgfs/inode.c
+@@ -490,13 +490,13 @@ HgfsPackSetattrRequest(struct iattr *iat
+ 
+       if (valid & ATTR_UID) {
+          attrV2->mask |= HGFS_ATTR_VALID_USERID;
+-         attrV2->userId = iattr->ia_uid;
++         attrV2->userId = from_kuid(&init_user_ns, iattr->ia_uid);
+          *changed = TRUE;
+       }
+ 
+       if (valid & ATTR_GID) {
+          attrV2->mask |= HGFS_ATTR_VALID_GROUPID;
+-         attrV2->groupId = iattr->ia_gid;
++         attrV2->groupId = from_kgid(&init_user_ns, iattr->ia_gid);
+          *changed = TRUE;
+       }
+ 
+@@ -593,13 +593,13 @@ HgfsPackSetattrRequest(struct iattr *iat
+ 
+       if (valid & ATTR_UID) {
+          attrV2->mask |= HGFS_ATTR_VALID_USERID;
+-         attrV2->userId = iattr->ia_uid;
++         attrV2->userId = from_kuid(&init_user_ns, iattr->ia_uid);
+          *changed = TRUE;
+       }
+ 
+       if (valid & ATTR_GID) {
+          attrV2->mask |= HGFS_ATTR_VALID_GROUPID;
+-         attrV2->groupId = iattr->ia_gid;
++         attrV2->groupId = from_kgid(&init_user_ns, iattr->ia_gid);
+          *changed = TRUE;
+       }
+ 
+@@ -1192,7 +1192,8 @@ HgfsMkdir(struct inode *dir,     // IN:
+              * a Linux machine and as root, but we might as well give it
+              * a go.
+              */
+-            HgfsSetUidGid(dir, dentry, current_fsuid(), current_fsgid());
++            HgfsSetUidGid(dir, dentry, from_kuid(&init_user_ns, current_fsuid()),
++                                       from_kgid(&init_user_ns, current_fsgid()));
+          }
+ 
+          /*
+--- a/modules/linux/vmhgfs/fsutil.c
++++ b/modules/linux/vmhgfs/fsutil.c
+@@ -639,14 +639,14 @@ HgfsChangeFileAttributes(struct inode *i
+     * the server didn't give us a uid or gid.
+     */
+    if (si->uidSet || (attr->mask & HGFS_ATTR_VALID_USERID) == 0) {
+-      inode->i_uid = si->uid;
++      inode->i_uid = make_kuid(&init_user_ns, si->uid);
+    } else {
+-      inode->i_uid = attr->userId;
++      inode->i_uid = make_kuid(&init_user_ns, attr->userId);
+    }
+    if (si->gidSet || (attr->mask & HGFS_ATTR_VALID_GROUPID) == 0) {
+-      inode->i_gid = si->gid;
++      inode->i_gid = make_kgid(&init_user_ns, si->gid);
+    } else {
+-      inode->i_gid = attr->groupId;
++      inode->i_gid = make_kgid(&init_user_ns, attr->groupId);
+    }
+ 
+    inode->i_rdev = 0;  /* Device nodes are not supported */
+@@ -1623,7 +1623,7 @@ HgfsSetUidGid(struct inode *parent,
+    struct iattr setUidGid;
+ 
+    setUidGid.ia_valid = ATTR_UID;
+-   setUidGid.ia_uid = uid;
++   setUidGid.ia_uid = make_kuid(&init_user_ns, uid);
+ 
+    /*
+     * Only set the gid if the host file system wouldn't have for us.  See the
+@@ -1631,7 +1631,7 @@ HgfsSetUidGid(struct inode *parent,
+     */
+    if (!parent || !(parent->i_mode & S_ISGID)) {
+       setUidGid.ia_valid |= ATTR_GID;
+-      setUidGid.ia_gid = gid;
++      setUidGid.ia_gid = make_kgid(&init_user_ns, gid);
+    }
+ 
+    /*
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/open-vm-tools.git/commitdiff/4a655ebc7c145d85c5e01f3b5a5c461de163baa2




More information about the pld-cvs-commit mailing list