xref: /aosp_15_r20/external/erofs-utils/include/erofs/dir.h (revision 33b1fccf6a0fada2c2875d400ed01119b7676ee5)
1 /* SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 */
2 #ifndef __EROFS_DIR_H
3 #define __EROFS_DIR_H
4 
5 #ifdef __cplusplus
6 extern "C"
7 {
8 #endif
9 
10 #include "internal.h"
11 
12 #define EROFS_READDIR_VALID_PNID	0x0001
13 #define EROFS_READDIR_DOTDOT_FOUND	0x0002
14 #define EROFS_READDIR_DOT_FOUND		0x0004
15 
16 #define EROFS_READDIR_ALL_SPECIAL_FOUND	\
17 	(EROFS_READDIR_DOTDOT_FOUND | EROFS_READDIR_DOT_FOUND)
18 
19 struct erofs_dir_context;
20 
21 /* callback function for iterating over inodes of EROFS */
22 typedef int (*erofs_readdir_cb)(struct erofs_dir_context *);
23 
24 /*
25  * Callers could use a wrapper to contain extra information.
26  *
27  * Note that callback can reuse `struct erofs_dir_context' with care
28  * to avoid stack overflow due to deep recursion:
29  *  - if fsck is true, |pnid|, |flags|, (optional)|cb| SHOULD be saved
30  *    to ensure the original state;
31  *  - if fsck is false, EROFS_READDIR_VALID_PNID SHOULD NOT be
32  *    set if |pnid| is inaccurate.
33  *
34  * Another way is to allocate a `struct erofs_dir_context' wraper
35  * with `struct inode' on heap, and chain them together for
36  * multi-level traversal to completely avoid recursion.
37  *
38  * |dname| may be WITHOUT the trailing '\0' and it's ONLY valid in
39  * the callback context. |de_namelen| is the exact dirent name length.
40  */
41 struct erofs_dir_context {
42 	/*
43 	 * During execution of |erofs_iterate_dir|, the function needs to
44 	 * read the values inside |erofs_inode* dir|. So it is important
45 	 * that the callback function does not modify struct pointed by
46 	 * |dir|. It is OK to repoint |dir| to other objects.
47 	 * Unfortunately, it's not possible to enforce this restriction
48 	 * with const keyword, as |erofs_iterate_dir| needs to modify
49 	 * struct pointed by |dir|.
50 	 */
51 	struct erofs_inode *dir;
52 	erofs_readdir_cb cb;
53 	erofs_nid_t pnid;		/* optional */
54 
55 	/* [OUT] the dirent which is under processing */
56 	const char *dname;		/* please see the comment above */
57 	erofs_nid_t de_nid;
58 	u8 de_namelen, de_ftype, flags;
59 	bool dot_dotdot;
60 };
61 
62 /* Iterate over inodes that are in directory */
63 int erofs_iterate_dir(struct erofs_dir_context *ctx, bool fsck);
64 /* Get a full pathname of the inode NID */
65 int erofs_get_pathname(struct erofs_sb_info *sbi, erofs_nid_t nid,
66 		       char *buf, size_t size);
67 
68 #ifdef __cplusplus
69 }
70 #endif
71 
72 #endif
73