diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2015-05-10 11:01:00 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-05-10 22:20:17 -0400 |
| commit | fab51e8ab25e1ad661ef8da42077de78477fba83 (patch) | |
| tree | 172e315fc3d3fec020327a9878e522f8efec0e0d /fs/namei.c | |
| parent | 4f697a5e173023a4f566339452a9d6f2cc7bd7dc (diff) | |
namei: take the treatment of absolute symlinks to get_link()
rather than letting the callers handle the jump-to-root part of
semantics, do it right in get_link() and return the rest of the
body for the caller to deal with - at that point it's treated
the same way as relative symlinks would be. And return NULL
when there's no "rest of the body" - those are treated the same
as pure jump symlink would be.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
| -rw-r--r-- | fs/namei.c | 49 |
1 files changed, 20 insertions, 29 deletions
diff --git a/fs/namei.c b/fs/namei.c index c5eb77a57974..c6ff9da69cec 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -918,9 +918,24 @@ const char *get_link(struct nameidata *nd) | |||
| 918 | res = inode->i_link; | 918 | res = inode->i_link; |
| 919 | if (!res) { | 919 | if (!res) { |
| 920 | res = inode->i_op->follow_link(dentry, &last->cookie); | 920 | res = inode->i_op->follow_link(dentry, &last->cookie); |
| 921 | if (IS_ERR_OR_NULL(res)) | 921 | if (IS_ERR_OR_NULL(res)) { |
| 922 | last->cookie = NULL; | 922 | last->cookie = NULL; |
| 923 | return res; | ||
| 924 | } | ||
| 925 | } | ||
| 926 | if (*res == '/') { | ||
| 927 | if (!nd->root.mnt) | ||
| 928 | set_root(nd); | ||
| 929 | path_put(&nd->path); | ||
| 930 | nd->path = nd->root; | ||
| 931 | path_get(&nd->root); | ||
| 932 | nd->inode = nd->path.dentry->d_inode; | ||
| 933 | nd->flags |= LOOKUP_JUMPED; | ||
| 934 | while (unlikely(*++res == '/')) | ||
| 935 | ; | ||
| 923 | } | 936 | } |
| 937 | if (!*res) | ||
| 938 | res = NULL; | ||
| 924 | return res; | 939 | return res; |
| 925 | } | 940 | } |
| 926 | 941 | ||
| @@ -1854,24 +1869,9 @@ OK: | |||
| 1854 | /* jumped */ | 1869 | /* jumped */ |
| 1855 | put_link(nd); | 1870 | put_link(nd); |
| 1856 | } else { | 1871 | } else { |
| 1857 | if (*s == '/') { | 1872 | nd->stack[nd->depth - 1].name = name; |
| 1858 | if (!nd->root.mnt) | 1873 | name = s; |
| 1859 | set_root(nd); | 1874 | continue; |
| 1860 | path_put(&nd->path); | ||
| 1861 | nd->path = nd->root; | ||
| 1862 | path_get(&nd->root); | ||
| 1863 | nd->flags |= LOOKUP_JUMPED; | ||
| 1864 | while (unlikely(*++s == '/')) | ||
| 1865 | ; | ||
| 1866 | } | ||
| 1867 | nd->inode = nd->path.dentry->d_inode; | ||
| 1868 | if (unlikely(!*s)) { | ||
| 1869 | put_link(nd); | ||
| 1870 | } else { | ||
| 1871 | nd->stack[nd->depth - 1].name = name; | ||
| 1872 | name = s; | ||
| 1873 | continue; | ||
| 1874 | } | ||
| 1875 | } | 1875 | } |
| 1876 | } | 1876 | } |
| 1877 | if (!d_can_lookup(nd->path.dentry)) { | 1877 | if (!d_can_lookup(nd->path.dentry)) { |
| @@ -2002,6 +2002,7 @@ static int trailing_symlink(struct nameidata *nd) | |||
| 2002 | if (unlikely(error)) | 2002 | if (unlikely(error)) |
| 2003 | return error; | 2003 | return error; |
| 2004 | nd->flags |= LOOKUP_PARENT; | 2004 | nd->flags |= LOOKUP_PARENT; |
| 2005 | nd->stack[0].name = NULL; | ||
| 2005 | s = get_link(nd); | 2006 | s = get_link(nd); |
| 2006 | if (unlikely(IS_ERR(s))) { | 2007 | if (unlikely(IS_ERR(s))) { |
| 2007 | terminate_walk(nd); | 2008 | terminate_walk(nd); |
| @@ -2009,16 +2010,6 @@ static int trailing_symlink(struct nameidata *nd) | |||
| 2009 | } | 2010 | } |
| 2010 | if (unlikely(!s)) | 2011 | if (unlikely(!s)) |
| 2011 | return 0; | 2012 | return 0; |
| 2012 | if (*s == '/') { | ||
| 2013 | if (!nd->root.mnt) | ||
| 2014 | set_root(nd); | ||
| 2015 | path_put(&nd->path); | ||
| 2016 | nd->path = nd->root; | ||
| 2017 | path_get(&nd->root); | ||
| 2018 | nd->flags |= LOOKUP_JUMPED; | ||
| 2019 | } | ||
| 2020 | nd->inode = nd->path.dentry->d_inode; | ||
| 2021 | nd->stack[0].name = NULL; | ||
| 2022 | return link_path_walk(s, nd); | 2013 | return link_path_walk(s, nd); |
| 2023 | } | 2014 | } |
| 2024 | 2015 | ||
