When the `path` contains symbolic links, erofs_ilookup() does not
function properly. This adds support for symlink files.

Signed-off-by: Hongzhen Luo <hongz...@linux.alibaba.com>
---
 lib/namei.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/lib/namei.c b/lib/namei.c
index 6f35ee6..dce2991 100644
--- a/lib/namei.c
+++ b/lib/namei.c
@@ -195,6 +195,22 @@ struct nameidata {
        unsigned int    ftype;
 };
 
+static int link_path_walk(const char *name, struct nameidata *nd);
+
+static int step_into_link(struct nameidata *nd, struct erofs_inode *vi)
+{
+       char buf[EROFS_MAX_BLOCK_SIZE];
+       int err;
+
+       if (vi->i_size > EROFS_MAX_BLOCK_SIZE)
+               return -EINVAL;
+       memset(buf, 0, sizeof(buf));
+       err = erofs_pread(vi, buf, vi->i_size, 0);
+       if (err)
+               return err;
+       return link_path_walk(buf, nd);
+}
+
 int erofs_namei(struct nameidata *nd, const char *name, unsigned int len)
 {
        erofs_nid_t nid = nd->nid;
@@ -233,6 +249,11 @@ int erofs_namei(struct nameidata *nd, const char *name, 
unsigned int len)
                        return PTR_ERR(de);
 
                if (de) {
+                       vi.nid = de->nid;
+                       ret = erofs_read_inode_from_disk(&vi);
+                       if (S_ISLNK(vi.i_mode)) {
+                               return step_into_link(nd, &vi);
+                       }
                        nd->nid = le64_to_cpu(de->nid);
                        return 0;
                }
@@ -243,7 +264,8 @@ int erofs_namei(struct nameidata *nd, const char *name, 
unsigned int len)
 
 static int link_path_walk(const char *name, struct nameidata *nd)
 {
-       nd->nid = nd->sbi->root_nid;
+       if (*name == '/')
+               nd->nid = nd->sbi->root_nid;
 
        while (*name == '/')
                name++;
@@ -274,6 +296,7 @@ int erofs_ilookup(const char *path, struct erofs_inode *vi)
        int ret;
        struct nameidata nd = { .sbi = vi->sbi };
 
+       nd.nid = nd.sbi->root_nid;
        ret = link_path_walk(path, &nd);
        if (ret)
                return ret;
-- 
2.43.5

Reply via email to