Linux Audio

Check our new training course

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