From: Huang Jianan <huangjia...@oppo.com> Signed-off-by: Huang Jianan <huangjia...@oppo.com> Signed-off-by: Guo Weichao <guoweic...@oppo.com> Signed-off-by: Gao Xiang <hsiang...@aol.com> --- fuse/main.c | 2 ++ fuse/namei.c | 14 ++++++++++---- fuse/read.c | 26 ++++++++++++++++++++++++++ fuse/read.h | 1 + include/erofs/internal.h | 1 + 5 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/fuse/main.c b/fuse/main.c index 5121e8325f32..563b2c378952 100644 --- a/fuse/main.c +++ b/fuse/main.c @@ -146,6 +146,7 @@ int erofs_getattr(const char *path, struct stat *stbuf) stbuf->st_blocks = stbuf->st_size / EROFS_BLKSIZ; stbuf->st_uid = v.i_uid; stbuf->st_gid = v.i_gid; + stbuf->st_rdev = v.i_rdev; stbuf->st_atime = sbi.build_time; stbuf->st_mtime = sbi.build_time; stbuf->st_ctime = sbi.build_time; @@ -153,6 +154,7 @@ int erofs_getattr(const char *path, struct stat *stbuf) } static struct fuse_operations erofs_ops = { + .readlink = erofs_readlink, .getattr = erofs_getattr, .readdir = erofs_readdir, .open = erofs_open, diff --git a/fuse/namei.c b/fuse/namei.c index cd747ad1be56..e79e77d1e3c9 100644 --- a/fuse/namei.c +++ b/fuse/namei.c @@ -11,6 +11,7 @@ #include <stdio.h> #include <errno.h> #include <sys/stat.h> +#include <sys/sysmacros.h> #include "erofs/defs.h" #include "erofs/print.h" @@ -37,6 +38,13 @@ static uint8_t get_path_token_len(const char *path) return len; } +static inline dev_t new_decode_dev(u32 dev) +{ + unsigned major = (dev & 0xfff00) >> 8; + unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00); + return makedev(major, minor); +} + int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi) { int ret; @@ -63,13 +71,11 @@ int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi) switch (vi->i_mode & S_IFMT) { case S_IFBLK: case S_IFCHR: - /* fixme: add special devices support - * vi->i_rdev = new_decode_dev(le32_to_cpu(v1->i_u.rdev)); - */ + vi->i_rdev = new_decode_dev(le32_to_cpu(v1->i_u.rdev)); break; case S_IFIFO: case S_IFSOCK: - /*fixme: vi->i_rdev = 0; */ + vi->i_rdev = 0; break; case S_IFREG: case S_IFLNK: diff --git a/fuse/read.c b/fuse/read.c index 446e0837cbc4..a55c0f2f78cd 100644 --- a/fuse/read.c +++ b/fuse/read.c @@ -70,3 +70,29 @@ int erofs_read(const char *path, char *buffer, size_t size, off_t offset, } } +int erofs_readlink(const char *path, char *buffer, size_t size) +{ + int ret; + erofs_nid_t nid; + size_t lnksz; + struct erofs_vnode v; + + ret = walk_path(path, &nid); + if (ret) + return ret; + + ret = erofs_iget_by_nid(nid, &v); + if (ret) + return ret; + + lnksz = min((size_t)v.i_size, size - 1); + + ret = erofs_read(path, buffer, lnksz, 0, NULL); + buffer[lnksz] = '\0'; + if (ret != (int)lnksz) + return ret; + + erofs_info("path:%s link=%s size=%llu", path, buffer, (unsigned long long)lnksz); + return 0; +} + diff --git a/fuse/read.h b/fuse/read.h index 3f4af1495510..e901c607dc91 100644 --- a/fuse/read.h +++ b/fuse/read.h @@ -12,5 +12,6 @@ int erofs_read(const char *path, char *buffer, size_t size, off_t offset, struct fuse_file_info *fi); +int erofs_readlink(const char *path, char *buffer, size_t size); #endif diff --git a/include/erofs/internal.h b/include/erofs/internal.h index f9e757316efe..77fa8d82c746 100644 --- a/include/erofs/internal.h +++ b/include/erofs/internal.h @@ -168,6 +168,7 @@ struct erofs_vnode { uint16_t i_uid; uint16_t i_gid; uint16_t i_nlink; + uint32_t i_rdev; /* if file is inline read inline data witch inode */ char *idata; -- 2.24.0