aboutsummaryrefslogtreecommitdiff
path: root/include/dir_tree.h
blob: ee630d58cd2a8baf1ad71cebd4feb8cf1d861a68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* SPDX-License-Identifier: GPL-3.0-or-later */
/*
 * dir_tree.h
 *
 * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
 */
#ifndef DIR_TREE_H
#define DIR_TREE_H

/**
 * @enum SQFS_TREE_FILTER_FLAGS
 *
 * @brief Filter flags for @ref sqfs_dir_reader_get_full_hierarchy
 */
typedef enum {
	/**
	 * @brief Omit device special files from the final tree.
	 */
	SQFS_TREE_NO_DEVICES = 0x01,

	/**
	 * @brief Omit socket files from the final tree.
	 */
	SQFS_TREE_NO_SOCKETS = 0x02,

	/**
	 * @brief Omit named pipes from the final tree.
	 */
	SQFS_TREE_NO_FIFO = 0x04,

	/**
	 * @brief Omit symbolic links from the final tree.
	 */
	SQFS_TREE_NO_SLINKS = 0x08,

	/**
	 * @brief Omit empty directories from the final tree.
	 *
	 * If a directory is not empty on-disk, but ends up empty after
	 * applying all the other filter rules, it is also omitted.
	 */
	SQFS_TREE_NO_EMPTY = 0x10,

	/**
	 * @brief Do not recurse into sub directories.
	 *
	 * If the start node is a directory, the tree deserializer will still
	 * recurse into it, but it will not go beyond that.
	 */
	SQFS_TREE_NO_RECURSE = 0x20,

	/**
	 * @brief Store the list of parent nodes all the way to the target node
	 *
	 * When traversing towards the selected node, also collect the chain
	 * of parent nodes with the subtree stored at the end.
	 */
	SQFS_TREE_STORE_PARENTS = 0x40,

	SQFS_TREE_ALL_FLAGS = 0x7F,
} SQFS_TREE_FILTER_FLAGS;

/**
 * @struct sqfs_tree_node_t
 *
 * @brief Encapsulates a node in the filesystem tree read by
 *        @ref sqfs_dir_reader_get_full_hierarchy.
 */
struct sqfs_tree_node_t {
	/**
	 * @brief Pointer to parent, NULL for the root node
	 */
	sqfs_tree_node_t *parent;

	/**
	 * @brief For directories, a linked list of children.
	 */
	sqfs_tree_node_t *children;

	/**
	 * @brief Linked list next pointer for children list.
	 */
	sqfs_tree_node_t *next;

	/**
	 * @brief Inode representing this element in the tree.
	 */
	sqfs_inode_generic_t *inode;

	/**
	 * @brief Resolved 32 bit user ID from the inode
	 */
	sqfs_u32 uid;

	/**
	 * @brief Resolved 32 bit group ID from the inode
	 */
	sqfs_u32 gid;

	/**
	 * @brief null-terminated entry name.
	 */
	sqfs_u8 name[];
};

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Recursively destroy a tree of @ref sqfs_tree_node_t nodes
 *
 * This function can be used to clean up after
 * @ref sqfs_dir_reader_get_full_hierarchy.
 *
 * @param root A pointer to the root node or NULL.
 */
SQFS_INTERNAL void sqfs_dir_tree_destroy(sqfs_tree_node_t *root);

/**
 * @brief Recursively destroy a tree of @ref sqfs_tree_node_t nodes
 *
 * @memberof sqfs_tree_node_t
 *
 * This function can be used to assemble an absolute path from a tree
 * node returned by @ref sqfs_dir_reader_get_full_hierarchy.
 *
 * The function recursively walks up the tree to assemble a path string. It
 * returns "/" for the root node and assembles paths beginning with "/" for
 * non-root nodes. The resulting path is slash separated, but (except for
 * the root) never ends with a slash.
 *
 * While walking the node list, the function enforces various invariantes. It
 * returns @ref SQFS_ERROR_LINK_LOOP if the list of parent pointers is cyclical,
 * @ref SQFS_ERROR_CORRUPTED if any node has an empty name, or a name that
 * contains '/' or equals ".." or ".". The function
 * returns @ref SQFS_ERROR_ARG_INVALID if given NULL node or the root has a name
 * set. Additionally, the function can return overflow or allocation failures
 * while constructing the path.
 *
 * The returned string needs to be free'd with @ref sqfs_free.
 *
 * @param node A pointer to a tree node.
 * @param out Returns a pointer to a string on success, set to NULL on failure.
 *
 * @return Zero on success, an @ref SQFS_ERROR value on failure.
 */
SQFS_INTERNAL int sqfs_tree_node_get_path(const sqfs_tree_node_t *node,
					  char **out);

/**
 * @brief High level helper function for deserializing the entire file system
 *        hierarchy into an in-memory tree structure.
 *
 * @memberof sqfs_dir_reader_t
 *
 * This function internally navigates to a specified inode using
 * @ref sqfs_dir_reader_find_by_path and starting from that recursively
 * deserializes the entire hierarchy into a tree structure holding all inodes.
 *
 * @param rd A pointer to a directory reader.
 * @param path A path to resolve into an inode. Forward or backward slashes can
 *             be used to separate path components. Resolving '.' or '..' is
 *             not supported. Can be set to NULL to get the root inode.
 * @param flags A combination of @ref SQFS_TREE_FILTER_FLAGS flags.
 * @param out Returns the top most tree node.
 *
 * @return Zero on success, an @ref SQFS_ERROR value on failure.
 */
SQFS_INTERNAL int sqfs_dir_reader_get_full_hierarchy(sqfs_dir_reader_t *rd,
						const sqfs_id_table_t *idtbl,
						const char *path,
						sqfs_u32 flags,
						sqfs_tree_node_t **out);

#ifdef __cplusplus
}
#endif

#endif /* DIR_TREE_H */