blob: 77656cae22e1007f4aee95ee407f1f1162fcbc0e [file] [log] [blame]
/* 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