[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