#include "volumes.h"
#include "extent_io.h"
#include "help.h"
-
-#define HEADER_MAGIC 0xbd5c25e27295668bULL
-#define MAX_PENDING_SIZE (256 * 1024)
-#define BLOCK_SIZE 1024
-#define BLOCK_MASK (BLOCK_SIZE - 1)
-
-#define COMPRESS_NONE 0
-#define COMPRESS_ZLIB 1
+#include "image/metadump.h"
#define MAX_WORKER_THREADS (32)
-struct meta_cluster_item {
- __le64 bytenr;
- __le32 size;
-} __attribute__ ((__packed__));
-
-struct meta_cluster_header {
- __le64 magic;
- __le64 bytenr;
- __le32 nritems;
- u8 compress;
-} __attribute__ ((__packed__));
-
-/* cluster header + index items + buffers */
-struct meta_cluster {
- struct meta_cluster_header header;
- struct meta_cluster_item items[];
-} __attribute__ ((__packed__));
-
-#define ITEMS_PER_CLUSTER ((BLOCK_SIZE - sizeof(struct meta_cluster)) / \
- sizeof(struct meta_cluster_item))
-
-struct fs_chunk {
- u64 logical;
- u64 physical;
- /*
- * physical_dup only store additonal physical for BTRFS_BLOCK_GROUP_DUP
- * currently restore only support single and DUP
- * TODO: modify this structure and the function related to this
- * structure for support RAID*
- */
- u64 physical_dup;
- u64 bytes;
- struct rb_node l;
- struct rb_node p;
- struct list_head list;
-};
-
struct async_work {
struct list_head list;
struct list_head ordered;
0x588982AFL,0x5D65F45EL,0x53516F4DL,0x56BD19BCL
};
-static int find_collision_brute_force(struct name *val, u32 name_len)
+/*
+ * Calculate a 4-byte suffix to match desired CRC32C
+ *
+ * @current_crc: CRC32C checksum of all bytes before the suffix
+ * @desired_crc: the checksum that we want to get after adding the suffix
+ *
+ * Outputs: @suffix: pointer to where the suffix will be written (4-bytes)
+ */
+static void find_collision_calc_suffix(unsigned long current_crc,
+ unsigned long desired_crc,
+ char *suffix)
+{
+ int i;
+
+ for(i = 3; i >= 0; i--) {
+ desired_crc = (desired_crc << 8)
+ ^ crc32c_rev_table[desired_crc >> 24 & 0xFF]
+ ^ ((current_crc >> i * 8) & 0xFF);
+ }
+ for (i = 0; i < 4; i++)
+ suffix[i] = (desired_crc >> i * 8) & 0xFF;
+}
+
+/*
+ * Check if suffix is valid according to our file name conventions
+ */
+static int find_collision_is_suffix_valid(const char *suffix)
+{
+ int i;
+ char c;
+
+ for (i = 0; i < 4; i++) {
+ c = suffix[i];
+ if (c < ' ' || c > 126 || c == '/')
+ return 0;
+ }
+ return 1;
+}
+
+static int find_collision_reverse_crc32c(struct name *val, u32 name_len)
{
unsigned long checksum;
+ unsigned long current_checksum;
int found = 0;
int i;
+ /* There are no same length collisions of 4 or less bytes */
+ if (name_len <= 4)
+ return 0;
checksum = crc32c(~1, val->val, name_len);
+ name_len -= 4;
memset(val->sub, ' ', name_len);
i = 0;
while (1) {
- if (crc32c(~1, val->sub, name_len) == checksum &&
+ current_checksum = crc32c(~1, val->sub, name_len);
+ find_collision_calc_suffix(current_checksum,
+ checksum,
+ val->sub + name_len);
+ if (find_collision_is_suffix_valid(val->sub + name_len) &&
memcmp(val->sub, val->val, val->len)) {
found = 1;
break;
return NULL;
}
- found = find_collision_brute_force(val, name_len);
+ found = find_collision_reverse_crc32c(val, name_len);
if (!found) {
warning(