*/
static int link_path_walk(const char *name, struct nameidata *nd)
{
+ int depth = 0; // depth <= nd->depth
int err;
nd->last_type = LAST_ROOT;
} while (unlikely(*name == '/'));
if (unlikely(!*name)) {
OK:
- /* pathname body, done */
- if (!nd->depth)
- return 0;
- name = nd->stack[nd->depth - 1].name;
- /* trailing symlink, done */
- if (!name)
+ /* pathname or trailing symlink, done */
+ if (!depth)
return 0;
/* last component of nested symlink */
+ name = nd->stack[--depth].name;
link = walk_component(nd, 0);
} else {
/* not the last component */
if (IS_ERR(link))
return PTR_ERR(link);
/* a symlink to follow */
- nd->stack[nd->depth - 1].name = name;
+ nd->stack[depth++].name = name;
name = link;
continue;
}
link = walk_component(nd, WALK_TRAILING);
if (link) {
nd->flags |= LOOKUP_PARENT;
- nd->stack[0].name = NULL;
}
return link;
}
if (unlikely(res)) {
nd->flags |= LOOKUP_PARENT;
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
- nd->stack[0].name = NULL;
return res;
}