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
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "memory-util.h"
#include "sysupdate-cache.h"
#define WEB_CACHE_ENTRIES_MAX 64U
#define WEB_CACHE_ITEM_SIZE_MAX (64U*1024U*1024U)
static WebCacheItem* web_cache_item_free(WebCacheItem *i) {
if (!i)
return NULL;
free(i->url);
return mfree(i);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(WebCacheItem*, web_cache_item_free);
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(web_cache_hash_ops, char, string_hash_func, string_compare_func, WebCacheItem, web_cache_item_free);
int web_cache_add_item(
Hashmap **web_cache,
const char *url,
bool verified,
const void *data,
size_t size) {
_cleanup_(web_cache_item_freep) WebCacheItem *item = NULL;
_cleanup_free_ char *u = NULL;
int r;
assert(web_cache);
assert(url);
assert(data || size == 0);
if (size > WEB_CACHE_ITEM_SIZE_MAX)
return -E2BIG;
item = web_cache_get_item(*web_cache, url, verified);
if (item && memcmp_nn(item->data, item->size, data, size) == 0)
return 0;
if (hashmap_size(*web_cache) >= (size_t) (WEB_CACHE_ENTRIES_MAX + !!hashmap_get(*web_cache, url)))
return -ENOSPC;
r = hashmap_ensure_allocated(web_cache, &web_cache_hash_ops);
if (r < 0)
return r;
u = strdup(url);
if (!u)
return -ENOMEM;
item = malloc(offsetof(WebCacheItem, data) + size + 1);
if (!item)
return -ENOMEM;
*item = (WebCacheItem) {
.url = TAKE_PTR(u),
.size = size,
.verified = verified,
};
/* Just to be extra paranoid, let's NUL terminate the downloaded buffer */
*(uint8_t*) mempcpy(item->data, data, size) = 0;
web_cache_item_free(hashmap_remove(*web_cache, url));
r = hashmap_put(*web_cache, item->url, item);
if (r < 0)
return r;
TAKE_PTR(item);
return 1;
}
WebCacheItem* web_cache_get_item(Hashmap *web_cache, const char *url, bool verified) {
WebCacheItem *i;
i = hashmap_get(web_cache, url);
if (!i)
return NULL;
if (i->verified != verified)
return NULL;
return i;
}
|