blob: 7c52c3f90ea9db08a3602e97d05210573da97fbc [file] [log] [blame]
Colin Cross28fa5bc2012-05-20 13:28:05 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBSPARSE_SPARSE_H_
18#define _LIBSPARSE_SPARSE_H_
19
20#include <stdbool.h>
Tao Baoe18c0312018-04-23 15:15:40 -070021#include <stddef.h>
Colin Cross28fa5bc2012-05-20 13:28:05 -070022#include <stdint.h>
23
Colin Cross099824c2014-04-18 13:54:12 -070024#ifdef __cplusplus
25extern "C" {
26#endif
27
Colin Cross28fa5bc2012-05-20 13:28:05 -070028struct sparse_file;
29
Tao Baoe18c0312018-04-23 15:15:40 -070030// The callbacks in sparse_file_callback() and sparse_file_foreach_chunk() take
31// size_t as the length type (was `int` in past). This allows clients to keep
32// their codes compatibile with both versions as needed.
33#define SPARSE_CALLBACK_USES_SIZE_T
34
Colin Cross28fa5bc2012-05-20 13:28:05 -070035/**
36 * sparse_file_new - create a new sparse file cookie
37 *
38 * @block_size - minimum size of a chunk
39 * @len - size of the expanded sparse file.
40 *
41 * Creates a new sparse_file cookie that can be used to associate data
42 * blocks. Can later be written to a file with a variety of options.
43 * block_size specifies the minimum size of a chunk in the file. The maximum
44 * size of the file is 2**32 * block_size (16TB for 4k block size).
45 *
46 * Returns the sparse file cookie, or NULL on error.
47 */
48struct sparse_file *sparse_file_new(unsigned int block_size, int64_t len);
49
50/**
51 * sparse_file_destroy - destroy a sparse file cookie
52 *
53 * @s - sparse file cookie
54 *
55 * Destroys a sparse file cookie. After destroy, all memory passed in to
56 * sparse_file_add_data can be freed by the caller
57 */
58void sparse_file_destroy(struct sparse_file *s);
59
60/**
61 * sparse_file_add_data - associate a data chunk with a sparse file
62 *
63 * @s - sparse file cookie
64 * @data - pointer to data block
65 * @len - length of the data block
66 * @block - offset in blocks into the sparse file to place the data chunk
67 *
68 * Associates a data chunk with a sparse file cookie. The region
69 * [block * block_size : block * block_size + len) must not already be used in
70 * the sparse file. If len is not a multiple of the block size the data
71 * will be padded with zeros.
72 *
73 * The data pointer must remain valid until the sparse file is closed or the
74 * data block is removed from the sparse file.
75 *
76 * Returns 0 on success, negative errno on error.
77 */
Hyeongseok Kime8d02c52020-08-10 12:11:57 +090078int sparse_file_add_data(struct sparse_file* s, void* data, uint64_t len, unsigned int block);
Colin Cross28fa5bc2012-05-20 13:28:05 -070079
80/**
81 * sparse_file_add_fill - associate a fill chunk with a sparse file
82 *
83 * @s - sparse file cookie
84 * @fill_val - 32 bit fill data
85 * @len - length of the fill block
86 * @block - offset in blocks into the sparse file to place the fill chunk
87 *
88 * Associates a chunk filled with fill_val with a sparse file cookie.
89 * The region [block * block_size : block * block_size + len) must not already
90 * be used in the sparse file. If len is not a multiple of the block size the
91 * data will be padded with zeros.
92 *
93 * Returns 0 on success, negative errno on error.
94 */
Hyeongseok Kime8d02c52020-08-10 12:11:57 +090095int sparse_file_add_fill(struct sparse_file* s, uint32_t fill_val, uint64_t len,
96 unsigned int block);
Colin Cross28fa5bc2012-05-20 13:28:05 -070097
98/**
99 * sparse_file_add_file - associate a chunk of a file with a sparse file
100 *
101 * @s - sparse file cookie
102 * @filename - filename of the file to be copied
103 * @file_offset - offset into the copied file
104 * @len - length of the copied block
105 * @block - offset in blocks into the sparse file to place the file chunk
106 *
107 * Associates a chunk of an existing file with a sparse file cookie.
108 * The region [block * block_size : block * block_size + len) must not already
109 * be used in the sparse file. If len is not a multiple of the block size the
110 * data will be padded with zeros.
111 *
112 * Allows adding large amounts of data to a sparse file without needing to keep
113 * it all mapped. File size is limited by available virtual address space,
114 * exceptionally large files may need to be added in multiple chunks.
115 *
116 * Returns 0 on success, negative errno on error.
117 */
Hyeongseok Kime8d02c52020-08-10 12:11:57 +0900118int sparse_file_add_file(struct sparse_file* s, const char* filename, int64_t file_offset,
119 uint64_t len, unsigned int block);
Colin Cross28fa5bc2012-05-20 13:28:05 -0700120
121/**
Colin Cross9e1f17e2012-04-25 18:31:39 -0700122 * sparse_file_add_file - associate a chunk of a file with a sparse file
123 *
124 * @s - sparse file cookie
125 * @filename - filename of the file to be copied
126 * @file_offset - offset into the copied file
127 * @len - length of the copied block
128 * @block - offset in blocks into the sparse file to place the file chunk
129 *
130 * Associates a chunk of an existing fd with a sparse file cookie.
131 * The region [block * block_size : block * block_size + len) must not already
132 * be used in the sparse file. If len is not a multiple of the block size the
133 * data will be padded with zeros.
134 *
135 * Allows adding large amounts of data to a sparse file without needing to keep
136 * it all mapped. File size is limited by available virtual address space,
137 * exceptionally large files may need to be added in multiple chunks.
138 *
139 * The fd must remain open until the sparse file is closed or the fd block is
140 * removed from the sparse file.
141 *
142 * Returns 0 on success, negative errno on error.
143 */
Hyeongseok Kime8d02c52020-08-10 12:11:57 +0900144int sparse_file_add_fd(struct sparse_file* s, int fd, int64_t file_offset, uint64_t len,
145 unsigned int block);
Colin Cross9e1f17e2012-04-25 18:31:39 -0700146
147/**
Colin Cross28fa5bc2012-05-20 13:28:05 -0700148 * sparse_file_write - write a sparse file to a file
149 *
150 * @s - sparse file cookie
151 * @fd - file descriptor to write to
152 * @gz - write a gzipped file
153 * @sparse - write in the Android sparse file format
154 * @crc - append a crc chunk
155 *
156 * Writes a sparse file to a file. If gz is true, the data will be passed
157 * through zlib. If sparse is true, the file will be written in the Android
158 * sparse file format. If sparse is false, the file will be written by seeking
159 * over unused chunks, producing a smaller file if the filesystem supports
160 * sparse files. If crc is true, the crc of the expanded data will be
161 * calculated and appended in a crc chunk.
162 *
163 * Returns 0 on success, negative errno on error.
164 */
165int sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse,
166 bool crc);
167
Colin Crossa21930b2012-04-26 14:24:35 -0700168/**
Colin Cross317a09e2012-05-24 17:15:43 -0700169 * sparse_file_len - return the length of a sparse file if written to disk
170 *
171 * @s - sparse file cookie
172 * @sparse - write in the Android sparse file format
173 * @crc - append a crc chunk
174 *
175 * Returns the size a sparse file would be on disk if it were written in the
176 * specified format. If sparse is true, this is the size of the data in the
177 * sparse format. If sparse is false, this is the size of the normal
178 * non-sparse file.
179 */
180int64_t sparse_file_len(struct sparse_file *s, bool sparse, bool crc);
181
182/**
Adrien Schildknechta26a6bd2016-11-30 11:49:47 -0800183 * sparse_file_block_size
184 *
185 * @s - sparse file cookie
186 */
187unsigned int sparse_file_block_size(struct sparse_file *s);
188
189/**
Colin Cross1e17b312012-05-21 16:35:45 -0700190 * sparse_file_callback - call a callback for blocks in sparse file
191 *
192 * @s - sparse file cookie
193 * @sparse - write in the Android sparse file format
194 * @crc - append a crc chunk
195 * @write - function to call for each block
196 * @priv - value that will be passed as the first argument to write
197 *
198 * Writes a sparse file by calling a callback function. If sparse is true, the
199 * file will be written in the Android sparse file format. If crc is true, the
200 * crc of the expanded data will be calculated and appended in a crc chunk.
201 * The callback 'write' will be called with data and length for each data,
202 * and with data==NULL to skip over a region (only used for non-sparse format).
203 * The callback should return negative on error, 0 on success.
204 *
205 * Returns 0 on success, negative errno on error.
206 */
207int sparse_file_callback(struct sparse_file *s, bool sparse, bool crc,
Tao Baoe18c0312018-04-23 15:15:40 -0700208 int (*write)(void *priv, const void *data, size_t len), void *priv);
Colin Cross1e17b312012-05-21 16:35:45 -0700209
210/**
Adrien Schildknechta26a6bd2016-11-30 11:49:47 -0800211 * sparse_file_foreach_chunk - call a callback for data blocks in sparse file
212 *
213 * @s - sparse file cookie
214 * @sparse - write in the Android sparse file format
215 * @crc - append a crc chunk
216 * @write - function to call for each block
217 * @priv - value that will be passed as the first argument to write
218 *
219 * The function has the same behavior as 'sparse_file_callback', except it only
220 * iterates on blocks that contain data.
221 *
222 * Returns 0 on success, negative errno on error.
223 */
224int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
Tao Baoe18c0312018-04-23 15:15:40 -0700225 int (*write)(void *priv, const void *data, size_t len, unsigned int block,
Adrien Schildknechta26a6bd2016-11-30 11:49:47 -0800226 unsigned int nr_blocks),
227 void *priv);
Sean Andersonf96466b2021-12-30 15:19:41 -0500228
229/**
230 * enum sparse_read_mode - The method to use when reading in files
231 * @SPARSE_READ_MODE_NORMAL: The input is a regular file. Constant chunks of
232 * data (including holes) will be be converted to
233 * fill chunks.
234 * @SPARSE_READ_MODE_SPARSE: The input is an Android sparse file.
235 * @SPARSE_READ_MODE_HOLE: The input is a regular file. Holes will be converted
236 * to "don't care" chunks. Other constant chunks will
237 * be converted to fill chunks.
238 */
239enum sparse_read_mode {
240 SPARSE_READ_MODE_NORMAL = false,
241 SPARSE_READ_MODE_SPARSE = true,
242 SPARSE_READ_MODE_HOLE,
243};
244
Adrien Schildknechta26a6bd2016-11-30 11:49:47 -0800245/**
Colin Cross0c4c47f2012-04-25 19:02:58 -0700246 * sparse_file_read - read a file into a sparse file cookie
247 *
248 * @s - sparse file cookie
249 * @fd - file descriptor to read from
Sean Andersonf96466b2021-12-30 15:19:41 -0500250 * @mode - mode to use when reading the input file
Colin Cross0c4c47f2012-04-25 19:02:58 -0700251 * @crc - verify the crc of a file in the Android sparse file format
252 *
Sean Andersonf96466b2021-12-30 15:19:41 -0500253 * Reads a file into a sparse file cookie. If @mode is
254 * %SPARSE_READ_MODE_SPARSE, the file is assumed to be in the Android sparse
255 * file format. If @mode is %SPARSE_READ_MODE_NORMAL, the file will be sparsed
256 * by looking for block aligned chunks of all zeros or another 32 bit value. If
257 * @mode is %SPARSE_READ_MODE_HOLE, the file will be sparsed like
258 * %SPARSE_READ_MODE_NORMAL, but holes in the file will be converted to "don't
259 * care" chunks. If crc is true, the crc of the sparse file will be verified.
Colin Cross0c4c47f2012-04-25 19:02:58 -0700260 *
261 * Returns 0 on success, negative errno on error.
262 */
Sean Andersonf96466b2021-12-30 15:19:41 -0500263int sparse_file_read(struct sparse_file *s, int fd, enum sparse_read_mode mode, bool crc);
Colin Cross0c4c47f2012-04-25 19:02:58 -0700264
265/**
Jerry Zhang50e60292018-06-05 11:44:52 -0700266 * sparse_file_import - import an existing sparse file
267 *
268 * @fd - file descriptor to read from
Colin Cross0c4c47f2012-04-25 19:02:58 -0700269 * @verbose - print verbose errors while reading the sparse file
270 * @crc - verify the crc of a file in the Android sparse file format
271 *
272 * Reads an existing sparse file into a sparse file cookie, recreating the same
273 * sparse cookie that was used to write it. If verbose is true, prints verbose
274 * errors when the sparse file is formatted incorrectly.
275 *
276 * Returns a new sparse file cookie on success, NULL on error.
277 */
278struct sparse_file *sparse_file_import(int fd, bool verbose, bool crc);
279
280/**
Jerry Zhang50e60292018-06-05 11:44:52 -0700281 * sparse_file_import_buf - import an existing sparse file from a buffer
282 *
283 * @buf - buffer to read from
Keith Moka3b72062021-12-31 05:09:32 +0000284 * @len - length of buffer
Jerry Zhang50e60292018-06-05 11:44:52 -0700285 * @verbose - print verbose errors while reading the sparse file
286 * @crc - verify the crc of a file in the Android sparse file format
287 *
288 * Reads existing sparse file data into a sparse file cookie, recreating the same
289 * sparse cookie that was used to write it. If verbose is true, prints verbose
290 * errors when the sparse file is formatted incorrectly.
291 *
292 * Returns a new sparse file cookie on success, NULL on error.
293 */
Keith Moka3b72062021-12-31 05:09:32 +0000294struct sparse_file* sparse_file_import_buf(char* buf, size_t len, bool verbose, bool crc);
Jerry Zhang50e60292018-06-05 11:44:52 -0700295
296/**
Colin Cross0c4c47f2012-04-25 19:02:58 -0700297 * sparse_file_import_auto - import an existing sparse or normal file
298 *
299 * @fd - file descriptor to read from
300 * @crc - verify the crc of a file in the Android sparse file format
Mohamad Ayyash80cc1f62015-03-31 12:09:29 -0700301 * @verbose - whether to use verbose logging
Colin Cross0c4c47f2012-04-25 19:02:58 -0700302 *
303 * Reads an existing sparse or normal file into a sparse file cookie.
304 * Attempts to determine if the file is sparse or not by looking for the sparse
305 * file magic number in the first 4 bytes. If the file is not sparse, the file
306 * will be sparsed by looking for block aligned chunks of all zeros or another
307 * 32 bit value. If crc is true, the crc of the sparse file will be verified.
308 *
309 * Returns a new sparse file cookie on success, NULL on error.
310 */
Mohamad Ayyash80cc1f62015-03-31 12:09:29 -0700311struct sparse_file *sparse_file_import_auto(int fd, bool crc, bool verbose);
Colin Cross0c4c47f2012-04-25 19:02:58 -0700312
Colin Crossbdc6d392012-05-02 15:18:22 -0700313/** sparse_file_resparse - rechunk an existing sparse file into smaller files
314 *
315 * @in_s - sparse file cookie of the existing sparse file
316 * @max_len - maximum file size
317 * @out_s - array of sparse file cookies
318 * @out_s_count - size of out_s array
319 *
320 * Splits chunks of an existing sparse file into smaller sparse files such that
321 * each sparse file is less than max_len. Returns the number of sparse_files
322 * that would have been written to out_s if out_s were big enough.
323 */
324int sparse_file_resparse(struct sparse_file *in_s, unsigned int max_len,
325 struct sparse_file **out_s, int out_s_count);
326
Colin Cross0c4c47f2012-04-25 19:02:58 -0700327/**
Colin Crossa21930b2012-04-26 14:24:35 -0700328 * sparse_file_verbose - set a sparse file cookie to print verbose errors
329 *
330 * @s - sparse file cookie
331 *
332 * Print verbose sparse file errors whenever using the sparse file cookie.
333 */
334void sparse_file_verbose(struct sparse_file *s);
335
336/**
337 * sparse_print_verbose - function called to print verbose errors
338 *
339 * By default, verbose errors will print to standard error.
340 * sparse_print_verbose may be overridden to log verbose errors somewhere else.
341 *
342 */
343extern void (*sparse_print_verbose)(const char *fmt, ...);
344
Colin Cross099824c2014-04-18 13:54:12 -0700345#ifdef __cplusplus
346}
347#endif
348
Colin Cross28fa5bc2012-05-20 13:28:05 -0700349#endif