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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/*
* xattr_reader.h - This file is part of libsquashfs
*
* Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef SQFS_XATTR_READER_H
#define SQFS_XATTR_READER_H
#include "sqfs/predef.h"
/**
* @file xattr_reader.h
*
* @brief Contains declarations for the @ref sqfs_xattr_reader_t.
*/
/**
* @struct sqfs_xattr_reader_t
*
* @brief Abstracts read access to extended attributes in a SquashFS filesystem
*
* SquashFS stores extended attributes using multiple levels of indirection.
* First of all, the key-value pairs of each inode (that has extended
* attributes) are deduplicated and stored consecutively in meta data blocks.
* Furthermore, a value can be stored out-of-band, i.e. it holds a reference to
* another location from which the value has to be read.
*
* For each unique set of key-value pairs, a descriptor object is generated
* that holds the location of the first pair, the number of pairs and the total
* size used on disk. The array of descriptor objects is stored in multiple
* meta data blocks. Each inode that has extended attributes holds a 32 bit
* index into the descriptor array.
*
* The third layer of indirection is yet another table that points to the
* locations of the previous two tables. Its location is in turn stored in
* the super block.
*
* The sqfs_xattr_reader_t data structure takes care of the low level details
* of loading and parsing the data.
*
* After creating an instance using @ref sqfs_xattr_reader_create, simply call
* @ref sqfs_xattr_reader_load_locations to load and parse all of the location
* tables. Then use @ref sqfs_xattr_reader_get_desc to resolve a 32 bit index
* from an inode to a descriptor structure. Use @ref sqfs_xattr_reader_seek_kv
* to point the reader to the start of the key-value pairs and the call
* @ref sqfs_xattr_reader_read_key and @ref sqfs_xattr_reader_read_value
* consecutively to read and decode each key-value pair.
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create an xattr reader
*
* @memberof sqfs_xattr_reader_t
*
* This function creates an object that abstracts away read only access to
* the extended attributes in a SquashFS filesystem.
*
* After creating a reader and before using it, call
* @ref sqfs_xattr_reader_load_locations to load and parse the location
* information required to look up xattr key-value pairs.
*
* All pointers passed to this function are stored internally for later use.
* Do not destroy any of the pointed to objects before destroying the xattr
* reader.
*
* @param file A pointer to a file object that contains the SquashFS filesystem
* @param super A pointer to the SquashFS super block required to find the
* location tables.
* @param cmp A pointer to a compressor used to uncompress the loaded meta data
* blocks.
*
* @return A pointer to a new xattr reader instance on success, NULL on
* allocation failure.
*/
SQFS_API sqfs_xattr_reader_t *sqfs_xattr_reader_create(sqfs_file_t *file,
sqfs_super_t *super,
sqfs_compressor_t *cmp);
/**
* @brief Destroy an xattr reader and free all memory used by it
*
* @memberof sqfs_xattr_reader_t
*
* @param xr A pointer to an xattr reader instance
*/
SQFS_API void sqfs_xattr_reader_destroy(sqfs_xattr_reader_t *xr);
/**
* @brief Load the locations of the xattr meta data blocks into memory
*
* @memberof sqfs_xattr_reader_t
*
* This function must be called explicitly after an xattr reader has been
* created to load the actual location table from disk.
*
* @return Zero on success, a negative @ref E_SQFS_ERROR value on failure.
*/
SQFS_API int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr);
/**
* @brief Resolve an xattr index from an inode to an xattr description
*
* @memberof sqfs_xattr_reader_t
*
* This function takes an xattr index from an extended inode type and resolves
* it to a descriptor that points to location of the key-value pairs and
* indicates how many key-value pairs to read from there.
*
* @param xr A pointer to an xattr reader instance
* @param idx The xattr index to resolve
* @param desc Used to return the description
*
* @return Zero on success, a negative @ref E_SQFS_ERROR value on failure.
*/
SQFS_API int sqfs_xattr_reader_get_desc(sqfs_xattr_reader_t *xr, sqfs_u32 idx,
sqfs_xattr_id_t *desc);
/**
* @brief Resolve an xattr index from an inode to an xattr description
*
* @memberof sqfs_xattr_reader_t
*
* This function takes an xattr descriptor object and seeks to the meta data
* block containing the key-value pairs. The individual pairs can then be read
* using consecutive calls to @ref sqfs_xattr_reader_read_key and
* @ref sqfs_xattr_reader_read_value.
*
* @param xr A pointer to an xattr reader instance
* @param desc The descriptor holding the location of the key-value pairs
*
* @return Zero on success, a negative @ref E_SQFS_ERROR value on failure.
*/
SQFS_API int sqfs_xattr_reader_seek_kv(sqfs_xattr_reader_t *xr,
const sqfs_xattr_id_t *desc);
/**
* @brief Read the next xattr key
*
* @memberof sqfs_xattr_reader_t
*
* After setting the start position using @ref sqfs_xattr_reader_seek_kv, this
* function reads and decodes an xattr key and advances the internal position
* indicator to the location after the key. The value can then be read using
* using @ref sqfs_xattr_reader_read_value. After reading the value, the next
* key can be read by calling this function again.
*
* @param xr A pointer to an xattr reader instance
* @param key_out Used to return the decoded key. The underlying memory can be
* released using a single free() call.
*
* @return Zero on success, a negative @ref E_SQFS_ERROR value on failure.
*/
SQFS_API
int sqfs_xattr_reader_read_key(sqfs_xattr_reader_t *xr,
sqfs_xattr_entry_t **key_out);
/**
* @brief Read the xattr value belonging to the last read key
*
* @memberof sqfs_xattr_reader_t
*
* After calling @ref sqfs_xattr_reader_read_key, this function can read and
* decode the asociated value. The internal location indicator is then advanced
* past the key to the next value, so @ref sqfs_xattr_reader_read_key can be
* called again to read the next key.
*
* @param xr A pointer to an xattr reader instance.
* @param key A pointer to the decoded key object.
* @param val_out Used to return the decoded value. The underlying memory can
* be released using a single free() call.
*
* @return Zero on success, a negative @ref E_SQFS_ERROR value on failure.
*/
SQFS_API
int sqfs_xattr_reader_read_value(sqfs_xattr_reader_t *xr,
const sqfs_xattr_entry_t *key,
sqfs_xattr_value_t **val_out);
#ifdef __cplusplus
}
#endif
#endif /* SQFS_XATTR_READER_H */
|