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