| /* SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 */ |
| #ifndef __EROFS_DIR_H |
| #define __EROFS_DIR_H |
| |
| #ifdef __cplusplus |
| extern "C" |
| { |
| #endif |
| |
| #include "internal.h" |
| |
| #define EROFS_READDIR_VALID_PNID 0x0001 |
| #define EROFS_READDIR_DOTDOT_FOUND 0x0002 |
| #define EROFS_READDIR_DOT_FOUND 0x0004 |
| |
| #define EROFS_READDIR_ALL_SPECIAL_FOUND \ |
| (EROFS_READDIR_DOTDOT_FOUND | EROFS_READDIR_DOT_FOUND) |
| |
| struct erofs_dir_context; |
| |
| /* callback function for iterating over inodes of EROFS */ |
| typedef int (*erofs_readdir_cb)(struct erofs_dir_context *); |
| |
| /* |
| * Callers could use a wrapper to contain extra information. |
| * |
| * Note that callback can reuse `struct erofs_dir_context' with care |
| * to avoid stack overflow due to deep recursion: |
| * - if fsck is true, |pnid|, |flags|, (optional)|cb| SHOULD be saved |
| * to ensure the original state; |
| * - if fsck is false, EROFS_READDIR_VALID_PNID SHOULD NOT be |
| * set if |pnid| is inaccurate. |
| * |
| * Another way is to allocate a `struct erofs_dir_context' wraper |
| * with `struct inode' on heap, and chain them together for |
| * multi-level traversal to completely avoid recursion. |
| * |
| * |dname| may be WITHOUT the trailing '\0' and it's ONLY valid in |
| * the callback context. |de_namelen| is the exact dirent name length. |
| */ |
| struct erofs_dir_context { |
| struct erofs_inode *dir; |
| erofs_readdir_cb cb; |
| erofs_nid_t pnid; /* optional */ |
| |
| /* [OUT] the dirent which is under processing */ |
| const char *dname; /* please see the comment above */ |
| erofs_nid_t de_nid; |
| u8 de_namelen, de_ftype, flags; |
| bool dot_dotdot; |
| }; |
| |
| /* Iterate over inodes that are in directory */ |
| int erofs_iterate_dir(struct erofs_dir_context *ctx, bool fsck); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif |