[PATCH 4/5] erofs-utils: support read special file
Huang Jianan
jnhuang95 at gmail.com
Fri Oct 16 00:39:58 AEDT 2020
Signed-off-by: Huang Jianan <huangjianan at oppo.com>
Signed-off-by: Guo Weichao <guoweichao at oppo.com>
---
fuse/getattr.c | 1 +
fuse/main.c | 1 +
fuse/namei.c | 14 ++++++++++----
fuse/read.c | 26 ++++++++++++++++++++++++++
fuse/read.h | 1 +
include/erofs/internal.h | 1 +
6 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/fuse/getattr.c b/fuse/getattr.c
index 542cf35..d2134f4 100644
--- a/fuse/getattr.c
+++ b/fuse/getattr.c
@@ -56,6 +56,7 @@ int erofs_getattr(const char *path, struct stat *stbuf)
stbuf->st_blocks = stbuf->st_size / EROFS_BLKSIZ;
stbuf->st_uid = le16_to_cpu(v.i_uid);
stbuf->st_gid = le16_to_cpu(v.i_gid);
+ stbuf->st_rdev = le32_to_cpu(v.i_rdev);
stbuf->st_atime = super.build_time;
stbuf->st_mtime = super.build_time;
stbuf->st_ctime = super.build_time;
diff --git a/fuse/main.c b/fuse/main.c
index fa9795e..8841013 100644
--- a/fuse/main.c
+++ b/fuse/main.c
@@ -113,6 +113,7 @@ static void signal_handle_sigsegv(int signal)
}
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 3503a8d..7ed1168 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 "logging.h"
@@ -39,6 +40,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;
@@ -65,13 +73,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 ffe976e..3ce5c4f 100644
--- a/fuse/read.c
+++ b/fuse/read.c
@@ -112,3 +112,29 @@ int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
return -EINVAL;
}
}
+
+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;
+
+ logi("path:%s link=%s size=%llu", path, buffer, lnksz);
+ return 0;
+}
\ No newline at end of file
diff --git a/fuse/read.h b/fuse/read.h
index f2fcebe..89d4b4c 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 cba3ce4..47ad96d 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -153,6 +153,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.25.1
More information about the Linux-erofs
mailing list