brintos

brintos / linux-shallow public Read only

0
0
Text · 2.7 KiB · c3b90ab Raw
101 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2017-2018 HUAWEI, Inc.4 *             https://www.huawei.com/5 * Copyright (C) 2022, Alibaba Cloud6 */7#include "internal.h"8 9static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx,10			       void *dentry_blk, struct erofs_dirent *de,11			       unsigned int nameoff0, unsigned int maxsize)12{13	const struct erofs_dirent *end = dentry_blk + nameoff0;14 15	while (de < end) {16		unsigned char d_type = fs_ftype_to_dtype(de->file_type);17		unsigned int nameoff = le16_to_cpu(de->nameoff);18		const char *de_name = (char *)dentry_blk + nameoff;19		unsigned int de_namelen;20 21		/* the last dirent in the block? */22		if (de + 1 >= end)23			de_namelen = strnlen(de_name, maxsize - nameoff);24		else25			de_namelen = le16_to_cpu(de[1].nameoff) - nameoff;26 27		/* a corrupted entry is found */28		if (nameoff + de_namelen > maxsize ||29		    de_namelen > EROFS_NAME_LEN) {30			erofs_err(dir->i_sb, "bogus dirent @ nid %llu",31				  EROFS_I(dir)->nid);32			DBG_BUGON(1);33			return -EFSCORRUPTED;34		}35 36		if (!dir_emit(ctx, de_name, de_namelen,37			      le64_to_cpu(de->nid), d_type))38			return 1;39		++de;40		ctx->pos += sizeof(struct erofs_dirent);41	}42	return 0;43}44 45static int erofs_readdir(struct file *f, struct dir_context *ctx)46{47	struct inode *dir = file_inode(f);48	struct erofs_buf buf = __EROFS_BUF_INITIALIZER;49	struct super_block *sb = dir->i_sb;50	unsigned long bsz = sb->s_blocksize;51	unsigned int ofs = erofs_blkoff(sb, ctx->pos);52	int err = 0;53	bool initial = true;54 55	buf.mapping = dir->i_mapping;56	while (ctx->pos < dir->i_size) {57		erofs_off_t dbstart = ctx->pos - ofs;58		struct erofs_dirent *de;59		unsigned int nameoff, maxsize;60 61		de = erofs_bread(&buf, dbstart, EROFS_KMAP);62		if (IS_ERR(de)) {63			erofs_err(sb, "fail to readdir of logical block %u of nid %llu",64				  erofs_blknr(sb, dbstart), EROFS_I(dir)->nid);65			err = PTR_ERR(de);66			break;67		}68 69		nameoff = le16_to_cpu(de->nameoff);70		if (nameoff < sizeof(struct erofs_dirent) || nameoff >= bsz) {71			erofs_err(sb, "invalid de[0].nameoff %u @ nid %llu",72				  nameoff, EROFS_I(dir)->nid);73			err = -EFSCORRUPTED;74			break;75		}76 77		maxsize = min_t(unsigned int, dir->i_size - dbstart, bsz);78		/* search dirents at the arbitrary position */79		if (initial) {80			initial = false;81			ofs = roundup(ofs, sizeof(struct erofs_dirent));82			ctx->pos = dbstart + ofs;83		}84 85		err = erofs_fill_dentries(dir, ctx, de, (void *)de + ofs,86					  nameoff, maxsize);87		if (err)88			break;89		ctx->pos = dbstart + maxsize;90		ofs = 0;91	}92	erofs_put_metabuf(&buf);93	return err < 0 ? err : 0;94}95 96const struct file_operations erofs_dir_fops = {97	.llseek		= generic_file_llseek,98	.read		= generic_read_dir,99	.iterate_shared	= erofs_readdir,100};101