21ab4e
From 557bb6c344247b1c4763943ec737aa6963ac5572 Mon Sep 17 00:00:00 2001
21ab4e
From: Mohammed Rafi KC <rkavunga@redhat.com>
21ab4e
Date: Wed, 3 May 2017 17:19:57 +0530
21ab4e
Subject: [PATCH 448/473] gfapi: fix handling of dot and double dot in path
21ab4e
21ab4e
This patch is to handle "." and ".." in file path. Which means
21ab4e
this special dentry names will be resolved before sending fops
21ab4e
on the path.
21ab4e
21ab4e
Backport of>
21ab4e
>Change-Id: I5e92f6d1ad1412bf432eb2488e53fb7731edb013
21ab4e
>BUG: 1447266
21ab4e
>Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
21ab4e
>Reviewed-on: https://review.gluster.org/17177
21ab4e
>Smoke: Gluster Build System <jenkins@build.gluster.org>
21ab4e
>Reviewed-by: Niels de Vos <ndevos@redhat.com>
21ab4e
>CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
21ab4e
>NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
21ab4e
>Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
21ab4e
21ab4e
Change-Id: I5e92f6d1ad1412bf432eb2488e53fb7731edb013
21ab4e
BUG: 1441280
21ab4e
Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
21ab4e
Reviewed-on: https://code.engineering.redhat.com/gerrit/106338
21ab4e
Reviewed-by: Poornima Gurusiddaiah <pgurusid@redhat.com>
21ab4e
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
21ab4e
---
21ab4e
 api/src/glfs-resolve.c   |  41 ++++++++----------
21ab4e
 libglusterfs/src/inode.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++
21ab4e
 libglusterfs/src/inode.h |  17 ++++++++
21ab4e
 3 files changed, 144 insertions(+), 24 deletions(-)
21ab4e
21ab4e
diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c
21ab4e
index d495cd2..a2be87f 100644
21ab4e
--- a/api/src/glfs-resolve.c
21ab4e
+++ b/api/src/glfs-resolve.c
21ab4e
@@ -25,12 +25,10 @@
21ab4e
 #include "syncop.h"
21ab4e
 #include "call-stub.h"
21ab4e
 #include "gfapi-messages.h"
21ab4e
-
21ab4e
+#include "inode.h"
21ab4e
 #include "glfs-internal.h"
21ab4e
 
21ab4e
 #define graphid_str(subvol) (uuid_utoa((unsigned char *)subvol->graph->graph_uuid))
21ab4e
-
21ab4e
-
21ab4e
 int
21ab4e
 glfs_first_lookup_safe (xlator_t *subvol)
21ab4e
 {
21ab4e
@@ -251,33 +249,26 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,
21ab4e
 	loc.parent = inode_ref (parent);
21ab4e
 	gf_uuid_copy (loc.pargfid, parent->gfid);
21ab4e
 
21ab4e
-        /* /.. and /. should point back to /
21ab4e
-           we lookup using inode and gfid of root
21ab4e
-           Fill loc.name so that we make use md-cache.
21ab4e
-           md-cache is not valid for nameless lookups.
21ab4e
-        */
21ab4e
+        /* At this point we should never have '.' or ".." in path */
21ab4e
         if (__is_root_gfid (parent->gfid) &&
21ab4e
-            (strcmp (component, "..") == 0)) {
21ab4e
-                loc.inode = inode_ref (parent);
21ab4e
-                loc.name = ".";
21ab4e
-        } else {
21ab4e
-                if (strcmp (component, ".") == 0)
21ab4e
-                        loc.inode = inode_ref (parent);
21ab4e
-                else if (strcmp (component, "..") == 0)
21ab4e
-                        loc.inode = inode_parent (parent, 0, 0);
21ab4e
-                else
21ab4e
-                        loc.inode = inode_grep (parent->table, parent,
21ab4e
-                                                component);
21ab4e
+            (strcmp (component, "/") == 0)) {
21ab4e
+                if (!force_lookup) {
21ab4e
+                        inode = inode_ref (parent);
21ab4e
+                } else {
21ab4e
+                        ret = glfs_resolve_base (fs, subvol, parent, &ciatt);
21ab4e
+                        if (!ret)
21ab4e
+                                inode = inode_ref (parent);
21ab4e
+                }
21ab4e
+                goto found;
21ab4e
         }
21ab4e
 
21ab4e
-
21ab4e
+        loc.inode = inode_grep (parent->table, parent, component);
21ab4e
 	if (loc.inode) {
21ab4e
 		gf_uuid_copy (loc.gfid, loc.inode->gfid);
21ab4e
 		reval = 1;
21ab4e
 
21ab4e
                 if (!(force_lookup || inode_needs_lookup (loc.inode, THIS))) {
21ab4e
 			inode = inode_ref (loc.inode);
21ab4e
-			ciatt.ia_type = inode->ia_type;
21ab4e
 			goto found;
21ab4e
 		}
21ab4e
 	} else {
21ab4e
@@ -357,8 +348,10 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,
21ab4e
         } else if (inode == loc.inode)
21ab4e
                 inode_ctx_set (inode, THIS, &ctx_value);
21ab4e
 found:
21ab4e
-	if (inode)
21ab4e
+	if (inode) {
21ab4e
+                ciatt.ia_type = inode->ia_type;
21ab4e
 		inode_lookup (inode);
21ab4e
+        }
21ab4e
 	if (iatt)
21ab4e
 		*iatt = ciatt;
21ab4e
 out:
21ab4e
@@ -384,6 +377,7 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at,
21ab4e
 	char       *next_component = NULL;
21ab4e
 	int         ret = -1;
21ab4e
 	struct iatt ciatt = {0, };
21ab4e
+        char        dentry_name[PATH_MAX]  = {0, };
21ab4e
 
21ab4e
 	DECLARE_OLD_THIS;
21ab4e
 	__GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
21ab4e
@@ -414,9 +408,8 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at,
21ab4e
 
21ab4e
 		if (parent)
21ab4e
 			inode_unref (parent);
21ab4e
-
21ab4e
 		parent = inode;
21ab4e
-
21ab4e
+                glusterfs_normalize_dentry (&parent, &component, dentry_name);
21ab4e
 		inode = glfs_resolve_component (fs, subvol, parent,
21ab4e
 						component, &ciatt,
21ab4e
 						/* force hard lookup on the last
21ab4e
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c
21ab4e
index 747c1f1..90a5608 100644
21ab4e
--- a/libglusterfs/src/inode.c
21ab4e
+++ b/libglusterfs/src/inode.c
21ab4e
@@ -2548,3 +2548,113 @@ inode_ctx_size (inode_t *inode)
21ab4e
 out:
21ab4e
         return size;
21ab4e
 }
21ab4e
+
21ab4e
+static void
21ab4e
+inode_parent_null_check(inode_t **parent, inode_t *inode, char **component)
21ab4e
+{
21ab4e
+        GF_VALIDATE_OR_GOTO ("inode", inode, out);
21ab4e
+        GF_VALIDATE_OR_GOTO ("inode", (*component), out);
21ab4e
+
21ab4e
+        if (!(*parent) && __is_root_gfid (inode->gfid)) {
21ab4e
+                *parent = inode_ref (inode);
21ab4e
+                *component = "/";
21ab4e
+        }
21ab4e
+out:
21ab4e
+        return;
21ab4e
+}
21ab4e
+
21ab4e
+/*
21ab4e
+ * This function changes component name and parent inode
21ab4e
+ * if the component name is either "." or ".."
21ab4e
+ *
21ab4e
+ * @Paramas:
21ab4e
+ * Parent : Parent inode of current dentry
21ab4e
+ * component : component name that we need to test
21ab4e
+ * dentry_name : Address for memory if need to change component.
21ab4e
+ *               The caller has to preallocate this memory with
21ab4e
+ *               PATH_MAX as the size.
21ab4e
+ *
21ab4e
+ * We return the updated parent inode and component in the
21ab4e
+ * respective structures.
21ab4e
+ *
21ab4e
+ * Basic Idea of the function:
21ab4e
+ *
21ab4e
+ * Example 1 :
21ab4e
+ * Path /out_dir/dir/in_dir/.
21ab4e
+ *     In put values :
21ab4e
+ *         parent = in_dir
21ab4e
+ *         component : "."
21ab4e
+ *
21ab4e
+ *     Out put values:
21ab4e
+ *         parent : dir
21ab4e
+ *         component : "in_dir"
21ab4e
+ *
21ab4e
+ * Example 2 :
21ab4e
+ * Path /out_dir/dir/in_dir/..
21ab4e
+ *     In put values :
21ab4e
+ *         parent = in_dir
21ab4e
+ *         component : ".."
21ab4e
+ *
21ab4e
+ *     Out put values:
21ab4e
+ *         parent : output_dir
21ab4e
+ *         component : "dir"
21ab4e
+ */
21ab4e
+void
21ab4e
+glusterfs_normalize_dentry (inode_t **parent, char **component,
21ab4e
+                          char *dentry_name)
21ab4e
+{
21ab4e
+        inode_t         *temp_inode             = NULL;
21ab4e
+        dentry_t        *dentry                 = NULL;
21ab4e
+
21ab4e
+        GF_VALIDATE_OR_GOTO ("inode", (*parent), out);
21ab4e
+        GF_VALIDATE_OR_GOTO ("inode", (*component), out);
21ab4e
+        GF_VALIDATE_OR_GOTO ("inode", (dentry_name), out);
21ab4e
+
21ab4e
+        /* After this point, there should not be "." or ".."
21ab4e
+         * in the path. Dot and double dots are replaced with
21ab4e
+         * appropriate base name and parent inode.
21ab4e
+         */
21ab4e
+
21ab4e
+        /* During the resolving, if it goes beyond the mount point
21ab4e
+         * we do lookup on the mount itself like "/.. " will be
21ab4e
+         * converted as "/"
21ab4e
+         */
21ab4e
+        if (strcmp (*component, ".") == 0) {
21ab4e
+                temp_inode = *parent;
21ab4e
+                *parent = inode_parent (*parent, 0, 0);
21ab4e
+                inode_parent_null_check (parent, temp_inode, component);
21ab4e
+                pthread_mutex_lock (&temp_inode->table->lock);
21ab4e
+                {
21ab4e
+                        dentry = __dentry_search_arbit (temp_inode);
21ab4e
+                        if (dentry) {
21ab4e
+                                snprintf (dentry_name, PATH_MAX, "%s",
21ab4e
+                                          dentry->name);
21ab4e
+                                *component = dentry_name;
21ab4e
+                        }
21ab4e
+                }
21ab4e
+                pthread_mutex_unlock (&temp_inode->table->lock);
21ab4e
+                inode_unref (temp_inode);
21ab4e
+        } else if (strcmp (*component, "..") == 0) {
21ab4e
+                temp_inode = *parent;
21ab4e
+                *parent = inode_parent (*parent, 0, 0);
21ab4e
+                inode_parent_null_check (parent, temp_inode, component);
21ab4e
+                inode_unref (temp_inode);
21ab4e
+
21ab4e
+                temp_inode = *parent;
21ab4e
+                *parent = inode_parent (*parent, 0, 0);
21ab4e
+                inode_parent_null_check (parent, temp_inode, component);
21ab4e
+                pthread_mutex_lock (&temp_inode->table->lock);
21ab4e
+                {
21ab4e
+                        dentry = __dentry_search_arbit (temp_inode);
21ab4e
+                        if (dentry) {
21ab4e
+                                snprintf (dentry_name, PATH_MAX, "%s",
21ab4e
+                                          dentry->name);
21ab4e
+                                *component = dentry_name;
21ab4e
+                        }
21ab4e
+                }
21ab4e
+                pthread_mutex_unlock (&temp_inode->table->lock);
21ab4e
+                inode_unref (temp_inode);
21ab4e
+        }
21ab4e
+out:
21ab4e
+        return;
21ab4e
+}
21ab4e
diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h
21ab4e
index 5289b15..e3c38bb 100644
21ab4e
--- a/libglusterfs/src/inode.h
21ab4e
+++ b/libglusterfs/src/inode.h
21ab4e
@@ -282,4 +282,21 @@ inode_has_dentry (inode_t *inode);
21ab4e
 size_t
21ab4e
 inode_ctx_size (inode_t *inode);
21ab4e
 
21ab4e
+/*
21ab4e
+ * This function is used to change the dentry from a path
21ab4e
+ * if it contains any "." or ".." .
21ab4e
+ *
21ab4e
+ * It replaces "." and ".." to proper bname after resolving
21ab4e
+ * and will change the component accordingly.
21ab4e
+ *
21ab4e
+ * This fucntion also replaces the parent inode based on the
21ab4e
+ * bname.
21ab4e
+ *
21ab4e
+ * We should give a allocated memory as a third argument to store
21ab4e
+ * the component in case if we are modifying it.
21ab4e
+ */
21ab4e
+
21ab4e
+void
21ab4e
+glusterfs_normalize_dentry (inode_t **parent, char **component,
21ab4e
+                            char *dentry_name);
21ab4e
 #endif /* _INODE_H */
21ab4e
-- 
21ab4e
1.8.3.1
21ab4e