|
@@ -1382,6 +1382,25 @@ unsigned int full_name_hash(const unsigned char *name, unsigned int len)
|
|
|
return end_name_hash(hash);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * We know there's a real path component here of at least
|
|
|
+ * one character.
|
|
|
+ */
|
|
|
+static inline unsigned long hash_name(const char *name, unsigned int *hashp)
|
|
|
+{
|
|
|
+ unsigned long hash = init_name_hash();
|
|
|
+ unsigned long len = 0, c;
|
|
|
+
|
|
|
+ c = (unsigned char)*name;
|
|
|
+ do {
|
|
|
+ len++;
|
|
|
+ hash = partial_name_hash(c, hash);
|
|
|
+ c = (unsigned char)name[len];
|
|
|
+ } while (c && c != '/');
|
|
|
+ *hashp = end_name_hash(hash);
|
|
|
+ return len;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Name resolution.
|
|
|
* This is the basic name resolution function, turning a pathname into
|
|
@@ -1402,31 +1421,22 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
|
|
|
|
|
/* At this point we know we have a real path component. */
|
|
|
for(;;) {
|
|
|
- unsigned long hash;
|
|
|
struct qstr this;
|
|
|
- unsigned int c;
|
|
|
+ long len;
|
|
|
int type;
|
|
|
|
|
|
err = may_lookup(nd);
|
|
|
if (err)
|
|
|
break;
|
|
|
|
|
|
+ len = hash_name(name, &this.hash);
|
|
|
this.name = name;
|
|
|
- c = *(const unsigned char *)name;
|
|
|
-
|
|
|
- hash = init_name_hash();
|
|
|
- do {
|
|
|
- name++;
|
|
|
- hash = partial_name_hash(c, hash);
|
|
|
- c = *(const unsigned char *)name;
|
|
|
- } while (c && (c != '/'));
|
|
|
- this.len = name - (const char *) this.name;
|
|
|
- this.hash = end_name_hash(hash);
|
|
|
+ this.len = len;
|
|
|
|
|
|
type = LAST_NORM;
|
|
|
- if (this.name[0] == '.') switch (this.len) {
|
|
|
+ if (name[0] == '.') switch (len) {
|
|
|
case 2:
|
|
|
- if (this.name[1] == '.') {
|
|
|
+ if (name[1] == '.') {
|
|
|
type = LAST_DOTDOT;
|
|
|
nd->flags |= LOOKUP_JUMPED;
|
|
|
}
|
|
@@ -1445,12 +1455,18 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* remove trailing slashes? */
|
|
|
- if (!c)
|
|
|
+ if (!name[len])
|
|
|
goto last_component;
|
|
|
- while (*++name == '/');
|
|
|
- if (!*name)
|
|
|
+ /*
|
|
|
+ * If it wasn't NUL, we know it was '/'. Skip that
|
|
|
+ * slash, and continue until no more slashes.
|
|
|
+ */
|
|
|
+ do {
|
|
|
+ len++;
|
|
|
+ } while (unlikely(name[len] == '/'));
|
|
|
+ if (!name[len])
|
|
|
goto last_component;
|
|
|
+ name += len;
|
|
|
|
|
|
err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW);
|
|
|
if (err < 0)
|