/* 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; }