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
|
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/*
* fragtbl.c
*
* Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
*/
#define SQFS_BUILDING_DLL
#include "internal.h"
int process_completed_fragment(sqfs_block_processor_t *proc, sqfs_block_t *frag,
sqfs_block_t **blk_out)
{
sqfs_u32 index, offset;
size_t size;
int err;
err = sqfs_frag_table_find_tail_end(proc->frag_tbl,
frag->checksum, frag->size,
&index, &offset);
if (err == 0)
goto out_duplicate;
if (proc->frag_block != NULL) {
size = proc->frag_block->size + frag->size;
if (size > proc->max_block_size) {
*blk_out = proc->frag_block;
proc->frag_block = NULL;
}
}
if (proc->frag_block == NULL) {
size = sizeof(sqfs_block_t) + proc->max_block_size;
err= sqfs_frag_table_append(proc->frag_tbl, 0, 0, &index);
if (err)
goto fail;
proc->frag_block = calloc(1, size);
if (proc->frag_block == NULL) {
err = SQFS_ERROR_ALLOC;
goto fail;
}
proc->frag_block->index = index;
proc->frag_block->flags = SQFS_BLK_FRAGMENT_BLOCK;
}
err = sqfs_frag_table_add_tail_end(proc->frag_tbl,
proc->frag_block->index,
proc->frag_block->size,
frag->size, frag->checksum);
if (err)
goto fail;
sqfs_inode_set_frag_location(frag->inode, proc->frag_block->index,
proc->frag_block->size);
if (proc->hooks != NULL && proc->hooks->pre_fragment_store != NULL) {
proc->hooks->pre_fragment_store(proc->user_ptr, frag);
}
memcpy(proc->frag_block->data + proc->frag_block->size,
frag->data, frag->size);
proc->frag_block->flags |= (frag->flags & SQFS_BLK_DONT_COMPRESS);
proc->frag_block->size += frag->size;
return 0;
fail:
free(*blk_out);
*blk_out = NULL;
return err;
out_duplicate:
sqfs_inode_set_frag_location(frag->inode, index, offset);
if (proc->hooks != NULL &&
proc->hooks->notify_fragment_discard != NULL) {
proc->hooks->notify_fragment_discard(proc->user_ptr, frag);
}
return 0;
}
|