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