]>
Commit | Line | Data |
---|---|---|
570df426 DS |
1 | #include "cache.h" |
2 | #include "chunk-format.h" | |
3 | #include "csum-file.h" | |
4 | ||
5 | /* | |
6 | * When writing a chunk-based file format, collect the chunks in | |
7 | * an array of chunk_info structs. The size stores the _expected_ | |
8 | * amount of data that will be written by write_fn. | |
9 | */ | |
10 | struct chunk_info { | |
11 | uint32_t id; | |
12 | uint64_t size; | |
13 | chunk_write_fn write_fn; | |
14 | }; | |
15 | ||
16 | struct chunkfile { | |
17 | struct hashfile *f; | |
18 | ||
19 | struct chunk_info *chunks; | |
20 | size_t chunks_nr; | |
21 | size_t chunks_alloc; | |
22 | }; | |
23 | ||
24 | struct chunkfile *init_chunkfile(struct hashfile *f) | |
25 | { | |
26 | struct chunkfile *cf = xcalloc(1, sizeof(*cf)); | |
27 | cf->f = f; | |
28 | return cf; | |
29 | } | |
30 | ||
31 | void free_chunkfile(struct chunkfile *cf) | |
32 | { | |
33 | if (!cf) | |
34 | return; | |
35 | free(cf->chunks); | |
36 | free(cf); | |
37 | } | |
38 | ||
39 | int get_num_chunks(struct chunkfile *cf) | |
40 | { | |
41 | return cf->chunks_nr; | |
42 | } | |
43 | ||
44 | void add_chunk(struct chunkfile *cf, | |
45 | uint32_t id, | |
46 | size_t size, | |
47 | chunk_write_fn fn) | |
48 | { | |
49 | ALLOC_GROW(cf->chunks, cf->chunks_nr + 1, cf->chunks_alloc); | |
50 | ||
51 | cf->chunks[cf->chunks_nr].id = id; | |
52 | cf->chunks[cf->chunks_nr].write_fn = fn; | |
53 | cf->chunks[cf->chunks_nr].size = size; | |
54 | cf->chunks_nr++; | |
55 | } | |
56 | ||
57 | int write_chunkfile(struct chunkfile *cf, void *data) | |
58 | { | |
59 | int i; | |
60 | uint64_t cur_offset = hashfile_total(cf->f); | |
61 | ||
62 | /* Add the table of contents to the current offset */ | |
63 | cur_offset += (cf->chunks_nr + 1) * CHUNK_TOC_ENTRY_SIZE; | |
64 | ||
65 | for (i = 0; i < cf->chunks_nr; i++) { | |
66 | hashwrite_be32(cf->f, cf->chunks[i].id); | |
67 | hashwrite_be64(cf->f, cur_offset); | |
68 | ||
69 | cur_offset += cf->chunks[i].size; | |
70 | } | |
71 | ||
72 | /* Trailing entry marks the end of the chunks */ | |
73 | hashwrite_be32(cf->f, 0); | |
74 | hashwrite_be64(cf->f, cur_offset); | |
75 | ||
76 | for (i = 0; i < cf->chunks_nr; i++) { | |
77 | off_t start_offset = hashfile_total(cf->f); | |
78 | int result = cf->chunks[i].write_fn(cf->f, data); | |
79 | ||
80 | if (result) | |
81 | return result; | |
82 | ||
83 | if (hashfile_total(cf->f) - start_offset != cf->chunks[i].size) | |
84 | BUG("expected to write %"PRId64" bytes to chunk %"PRIx32", but wrote %"PRId64" instead", | |
85 | cf->chunks[i].size, cf->chunks[i].id, | |
86 | hashfile_total(cf->f) - start_offset); | |
87 | } | |
88 | ||
89 | return 0; | |
90 | } |