All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gao Xiang via Linux-erofs <linux-erofs@lists.ozlabs.org>
To: linux-erofs@lists.ozlabs.org
Subject: [WIP] [PATCH v4 09/12] erofs-utils: fuse: clean up readdir
Date: Sun, 15 Nov 2020 02:25:14 +0800	[thread overview]
Message-ID: <20201114182517.9738-10-hsiangkao@aol.com> (raw)
In-Reply-To: <20201114182517.9738-1-hsiangkao@aol.com>

Signed-off-by: Gao Xiang <hsiangkao@aol.com>
---
 fuse/main.c   |   2 +-
 fuse/readir.c | 155 +++++++++++++++++++++++---------------------------
 fuse/readir.h |   4 +-
 3 files changed, 74 insertions(+), 87 deletions(-)

diff --git a/fuse/main.c b/fuse/main.c
index 9ac8149c88d9..a4b7a3692c19 100644
--- a/fuse/main.c
+++ b/fuse/main.c
@@ -182,7 +182,7 @@ static int erofsfuse_readlink(const char *path, char *buffer, size_t size)
 static struct fuse_operations erofs_ops = {
 	.readlink = erofsfuse_readlink,
 	.getattr = erofs_getattr,
-	.readdir = erofs_readdir,
+	.readdir = erofsfuse_readdir,
 	.open = erofs_open,
 	.read = erofsfuse_read,
 	.init = erofs_init,
diff --git a/fuse/readir.c b/fuse/readir.c
index a405dd702d84..2e90c95c38aa 100644
--- a/fuse/readir.c
+++ b/fuse/readir.c
@@ -4,114 +4,101 @@
  *
  * Created by Li Guifu <blucerlee@gmail.com>
  */
-#include "readir.h"
-#include <errno.h>
-#include <linux/fs.h>
-#include <sys/stat.h>
+#include <fuse.h>
+#include <fuse_opt.h>
 
-#include "erofs/defs.h"
 #include "erofs/internal.h"
-#include "erofs_fs.h"
-#include "erofs/io.h"
 #include "erofs/print.h"
 
-erofs_nid_t split_entry(char *entry, off_t ofs, char *end, char *name,
-			uint32_t dirend)
+static int erofs_fill_dentries(struct erofs_inode *dir,
+			       fuse_fill_dir_t filler, void *buf,
+			       void *dblk, unsigned int nameoff,
+			       unsigned int maxsize)
 {
-	struct erofs_dirent *de = (struct erofs_dirent *)(entry + ofs);
-	uint16_t nameoff = le16_to_cpu(de->nameoff);
-	const char *de_name = entry + nameoff;
-	uint32_t de_namelen;
-
-	if ((void *)(de + 1) >= (void *)end)
-		de_namelen = strnlen(de_name, dirend - nameoff);
-	else
-		de_namelen = le16_to_cpu(de[1].nameoff) - nameoff;
-
-	memcpy(name, de_name, de_namelen);
-	name[de_namelen] = '\0';
-	return le64_to_cpu(de->nid);
-}
-
-int fill_dir(char *entrybuf, fuse_fill_dir_t filler, void *buf,
-	     uint32_t dirend)
-{
-	uint32_t ofs;
-	uint16_t nameoff;
-	char *end;
-	char name[EROFS_BLKSIZ];
-
-	nameoff = le16_to_cpu(((struct erofs_dirent *)entrybuf)->nameoff);
-	end = entrybuf + nameoff;
-	ofs = 0;
-	while (ofs < nameoff) {
-		(void)split_entry(entrybuf, ofs, end, name, dirend);
-		filler(buf, name, NULL, 0);
-		ofs += sizeof(struct erofs_dirent);
+	struct erofs_dirent *de = dblk;
+	const struct erofs_dirent *end = dblk + nameoff;
+	char namebuf[EROFS_NAME_LEN];
+
+	while (de < end) {
+		const char *de_name;
+		unsigned int de_namelen;
+
+		nameoff = le16_to_cpu(de->nameoff);
+		de_name = (char *)dblk + nameoff;
+
+		/* the last dirent in the block? */
+		if (de + 1 >= end)
+			de_namelen = strnlen(de_name, maxsize - nameoff);
+		else
+			de_namelen = le16_to_cpu(de[1].nameoff) - nameoff;
+
+		/* a corrupted entry is found */
+		if (nameoff + de_namelen > maxsize ||
+		    de_namelen > EROFS_NAME_LEN) {
+			erofs_err("bogus dirent @ nid %llu", dir->nid | 0ULL);
+			DBG_BUGON(1);
+			return -EFSCORRUPTED;
+		}
+
+		memcpy(namebuf, de_name, de_namelen);
+		namebuf[de_namelen] = '\0';
+
+		filler(buf, namebuf, NULL, 0);
+		++de;
 	}
-
 	return 0;
 }
 
-/** Function to add an entry in a readdir() operation
- *
- * @param buf the buffer passed to the readdir() operation
- * @param name the file name of the directory entry
- * @param stat file attributes, can be NULL
- * @param off offset of the next entry or zero
- * @return 1 if buffer is full, zero otherwise
- */
-int erofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
-		  off_t offset, struct fuse_file_info *fi)
+int erofsfuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+		      off_t offset, struct fuse_file_info *fi)
 {
 	int ret;
-	struct erofs_inode v;
-	char dirsbuf[EROFS_BLKSIZ];
-	uint32_t dir_nr, dir_off, nr_cnt;
+	struct erofs_inode dir;
+	char dblk[EROFS_BLKSIZ];
+	erofs_off_t pos;
 
 	erofs_dbg("readdir:%s offset=%llu", path, (long long)offset);
 	UNUSED(fi);
 
-	ret = erofs_ilookup(path, &v);
+	ret = erofs_ilookup(path, &dir);
 	if (ret)
 		return ret;
 
-	erofs_dbg("path=%s nid = %llu", path, v.nid | 0ULL);
+	erofs_dbg("path=%s nid = %llu", path, dir.nid | 0ULL);
 
-	if (!S_ISDIR(v.i_mode))
+	if (!S_ISDIR(dir.i_mode))
 		return -ENOTDIR;
 
-	if (!v.i_size)
+	if (!dir.i_size)
 		return 0;
 
-	dir_nr = erofs_blknr(v.i_size);
-	dir_off = erofs_blkoff(v.i_size);
-	nr_cnt = 0;
-
-	erofs_dbg("dir_size=%llu dir_nr = %u dir_off=%u",
-		  v.i_size | 0ULL, dir_nr, dir_off);
-
-	while (nr_cnt < dir_nr) {
-		memset(dirsbuf, 0, sizeof(dirsbuf));
-		ret = blk_read(dirsbuf, v.u.i_blkaddr + nr_cnt, 1);
-		if (ret < 0)
-			return -EIO;
-		fill_dir(dirsbuf, filler, buf, EROFS_BLKSIZ);
-		++nr_cnt;
-	}
-
-	if (v.datalayout == EROFS_INODE_FLAT_INLINE) {
-		off_t addr;
-
-		addr = iloc(v.nid) + v.inode_isize + v.xattr_isize;
-
-		memset(dirsbuf, 0, sizeof(dirsbuf));
-		ret = dev_read(dirsbuf, addr, dir_off);
-		if (ret < 0)
-			return -EIO;
-		fill_dir(dirsbuf, filler, buf, dir_off);
+	pos = 0;
+	while (pos < dir.i_size) {
+		unsigned int nameoff, maxsize;
+		struct erofs_dirent *de;
+
+		maxsize = min_t(unsigned int, EROFS_BLKSIZ,
+				dir.i_size - pos);
+		ret = erofs_pread(&dir, dblk, maxsize, pos);
+		if (ret)
+			return ret;
+
+		de = (struct erofs_dirent *)dblk;
+		nameoff = le16_to_cpu(de->nameoff);
+		if (nameoff < sizeof(struct erofs_dirent) ||
+		    nameoff >= PAGE_SIZE) {
+			erofs_err("invalid de[0].nameoff %u @ nid %llu",
+				  nameoff, dir.nid | 0ULL);
+			ret = -EFSCORRUPTED;
+			break;
+		}
+
+		ret = erofs_fill_dentries(&dir, filler, buf,
+					  dblk, nameoff, maxsize);
+		if (ret)
+			break;
+		pos += maxsize;
 	}
-
 	return 0;
 }
 
diff --git a/fuse/readir.h b/fuse/readir.h
index ee2ab8bdd0f0..16b878fe9f29 100644
--- a/fuse/readir.h
+++ b/fuse/readir.h
@@ -10,8 +10,8 @@
 #include <fuse.h>
 #include <fuse_opt.h>
 
-int erofs_readdir(const char *path, void *buffer, fuse_fill_dir_t filler,
-	       off_t offset, struct fuse_file_info *fi);
+int erofsfuse_readdir(const char *path, void *buffer, fuse_fill_dir_t filler,
+		      off_t offset, struct fuse_file_info *fi);
 
 
 #endif
-- 
2.24.0


  parent reply	other threads:[~2020-11-14 18:27 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20201114182517.9738-1-hsiangkao.ref@aol.com>
2020-11-14 18:25 ` [WIP] [PATCH v4 00/12] erofs-utils: introduce fuse implementation Gao Xiang via Linux-erofs
2020-11-14 18:25   ` [WIP] [PATCH v4 01/12] " Gao Xiang via Linux-erofs
2020-11-14 18:25   ` [WIP] [PATCH v4 02/12] erofs-utils: fuse: add special file support Gao Xiang via Linux-erofs
2020-11-14 18:25   ` [WIP] [PATCH v4 03/12] erofs-utils: fuse: add compressed " Gao Xiang via Linux-erofs
2020-11-14 18:25   ` [WIP] [PATCH v4 04/12] erofs-utils: fuse: clean up path walking Gao Xiang via Linux-erofs
2020-11-14 18:25   ` [WIP] [PATCH v4 05/12] erofs: clean up compress data read Gao Xiang via Linux-erofs
2020-11-14 18:25   ` [WIP] [PATCH v4 06/12] erofs-utils: fuse: get rid of erofs_vnode Gao Xiang via Linux-erofs
2020-11-14 18:25   ` [WIP] [PATCH v4 07/12] erofs-utils: fuse: move namei.c to lib/ Gao Xiang via Linux-erofs
2020-11-14 18:25   ` [WIP] [PATCH v4 08/12] erofs-utils: fuse: kill read.c Gao Xiang via Linux-erofs
2020-11-14 18:25   ` Gao Xiang via Linux-erofs [this message]
2020-11-14 18:27   ` [WIP] [PATCH v4 10/12] erofs-utils: fuse: rename readir.c to dir.c Gao Xiang via Linux-erofs
2020-11-14 18:27     ` [WIP] [PATCH v4 11/12] erofs-utils: fuse: cleanup main.c Gao Xiang via Linux-erofs
2020-11-14 18:27     ` [WIP] [PATCH v4 12/12] erofs-utils: fuse: fix up configure.ac / Makefile.am Gao Xiang via Linux-erofs

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201114182517.9738-10-hsiangkao@aol.com \
    --to=linux-erofs@lists.ozlabs.org \
    --cc=hsiangkao@aol.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.