diff options
-rw-r--r-- | src/util/disk_cache.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/src/util/disk_cache.c b/src/util/disk_cache.c index f5e114513e0..f8e994853c1 100644 --- a/src/util/disk_cache.c +++ b/src/util/disk_cache.c @@ -38,6 +38,7 @@ #include <errno.h> #include <dirent.h> +#include "util/crc32.h" #include "util/u_atomic.h" #include "util/mesa-sha1.h" #include "util/ralloc.h" @@ -709,6 +710,19 @@ disk_cache_put(struct disk_cache *cache, if (*cache->size + size > cache->max_size) evict_random_item(cache); + /* Create CRC of the data and store at the start of the file. We will + * read this when restoring the cache and use it to check for corruption. + */ + uint32_t crc32 = util_hash_crc32(data, size); + size_t crc_size = sizeof(crc32); + for (len = 0; len < crc_size; len += ret) { + ret = write(fd, ((uint8_t *) &crc32) + len, crc_size - len); + if (ret == -1) { + unlink(filename_tmp); + goto done; + } + } + /* Now, finally, write out the contents to the temporary file, then * rename them atomically to the destination filename, and also * perform an atomic increment of the total cache size. @@ -723,6 +737,7 @@ disk_cache_put(struct disk_cache *cache, rename(filename_tmp, filename); + size += crc_size; p_atomic_add(cache->size, size); done: @@ -765,17 +780,33 @@ disk_cache_get(struct disk_cache *cache, cache_key key, size_t *size) if (data == NULL) goto fail; - for (len = 0; len < sb.st_size; len += ret) { - ret = read(fd, data + len, sb.st_size - len); + /* Load the CRC that was created when the file was written. */ + uint32_t crc32; + size_t crc_size = sizeof(crc32); + assert(sb.st_size > crc_size); + for (len = 0; len < crc_size; len += ret) { + ret = read(fd, ((uint8_t *) &crc32) + len, crc_size - len); if (ret == -1) goto fail; } + /* Load the actual cache data. */ + size_t cache_data_size = sb.st_size - crc_size; + for (len = 0; len < cache_data_size; len += ret) { + ret = read(fd, data + len, cache_data_size - len); + if (ret == -1) + goto fail; + } + + /* Check the data for corruption */ + if (crc32 != util_hash_crc32(data, cache_data_size)) + goto fail; + free(filename); close(fd); if (size) - *size = sb.st_size; + *size = cache_data_size; return data; |