1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2017-2018 HUAWEI, Inc.
4 * http://www.huawei.com/
5 * Created by Gao Xiang <gaoxiang25@huawei.com>
9 static void debug_one_dentry(unsigned char d_type
, const char *de_name
,
10 unsigned int de_namelen
)
12 #ifdef CONFIG_EROFS_FS_DEBUG
13 /* since the on-disk name could not have the trailing '\0' */
14 unsigned char dbg_namebuf
[EROFS_NAME_LEN
+ 1];
16 memcpy(dbg_namebuf
, de_name
, de_namelen
);
17 dbg_namebuf
[de_namelen
] = '\0';
19 erofs_dbg("found dirent %s de_len %u d_type %d", dbg_namebuf
,
24 static int erofs_fill_dentries(struct inode
*dir
, struct dir_context
*ctx
,
25 void *dentry_blk
, unsigned int *ofs
,
26 unsigned int nameoff
, unsigned int maxsize
)
28 struct erofs_dirent
*de
= dentry_blk
+ *ofs
;
29 const struct erofs_dirent
*end
= dentry_blk
+ nameoff
;
33 unsigned int de_namelen
;
36 d_type
= fs_ftype_to_dtype(de
->file_type
);
38 nameoff
= le16_to_cpu(de
->nameoff
);
39 de_name
= (char *)dentry_blk
+ nameoff
;
41 /* the last dirent in the block? */
43 de_namelen
= strnlen(de_name
, maxsize
- nameoff
);
45 de_namelen
= le16_to_cpu(de
[1].nameoff
) - nameoff
;
47 /* a corrupted entry is found */
48 if (nameoff
+ de_namelen
> maxsize
||
49 de_namelen
> EROFS_NAME_LEN
) {
50 erofs_err(dir
->i_sb
, "bogus dirent @ nid %llu",
56 debug_one_dentry(d_type
, de_name
, de_namelen
);
57 if (!dir_emit(ctx
, de_name
, de_namelen
,
58 le64_to_cpu(de
->nid
), d_type
))
59 /* stopped by some reason */
62 *ofs
+= sizeof(struct erofs_dirent
);
68 static int erofs_readdir(struct file
*f
, struct dir_context
*ctx
)
70 struct inode
*dir
= file_inode(f
);
71 struct address_space
*mapping
= dir
->i_mapping
;
72 const size_t dirsize
= i_size_read(dir
);
73 unsigned int i
= ctx
->pos
/ EROFS_BLKSIZ
;
74 unsigned int ofs
= ctx
->pos
% EROFS_BLKSIZ
;
78 while (ctx
->pos
< dirsize
) {
79 struct page
*dentry_page
;
80 struct erofs_dirent
*de
;
81 unsigned int nameoff
, maxsize
;
83 dentry_page
= read_mapping_page(mapping
, i
, NULL
);
84 if (dentry_page
== ERR_PTR(-ENOMEM
)) {
87 } else if (IS_ERR(dentry_page
)) {
89 "fail to readdir of logical block %u of nid %llu",
90 i
, EROFS_I(dir
)->nid
);
95 de
= (struct erofs_dirent
*)kmap(dentry_page
);
97 nameoff
= le16_to_cpu(de
->nameoff
);
99 if (nameoff
< sizeof(struct erofs_dirent
) ||
100 nameoff
>= PAGE_SIZE
) {
102 "invalid de[0].nameoff %u @ nid %llu",
103 nameoff
, EROFS_I(dir
)->nid
);
108 maxsize
= min_t(unsigned int,
109 dirsize
- ctx
->pos
+ ofs
, PAGE_SIZE
);
111 /* search dirents at the arbitrary position */
115 ofs
= roundup(ofs
, sizeof(struct erofs_dirent
));
120 err
= erofs_fill_dentries(dir
, ctx
, de
, &ofs
,
125 put_page(dentry_page
);
127 ctx
->pos
= blknr_to_addr(i
) + ofs
;
134 return err
< 0 ? err
: 0;
137 const struct file_operations erofs_dir_fops
= {
138 .llseek
= generic_file_llseek
,
139 .read
= generic_read_dir
,
140 .iterate_shared
= erofs_readdir
,