summaryrefslogtreecommitdiff
path: root/btrfs-show-super.c
diff options
context:
space:
mode:
Diffstat (limited to 'btrfs-show-super.c')
-rw-r--r--btrfs-show-super.c79
1 files changed, 58 insertions, 21 deletions
diff --git a/btrfs-show-super.c b/btrfs-show-super.c
index d8ad69e..051bd11 100644
--- a/btrfs-show-super.c
+++ b/btrfs-show-super.c
@@ -144,17 +144,15 @@ static int load_and_dump_sb(char *filename, int fd, u64 sb_bytenr, int full,
ret = pread64(fd, super_block_data, BTRFS_SUPER_INFO_SIZE, sb_bytenr);
if (ret != BTRFS_SUPER_INFO_SIZE) {
- int e = errno;
-
/* check if the disk if too short for further superblock */
- if (ret == 0 && e == 0)
+ if (ret == 0 && errno == 0)
return 0;
fprintf(stderr,
"ERROR: Failed to read the superblock on %s at %llu\n",
filename, (unsigned long long)sb_bytenr);
fprintf(stderr,
- "ERROR: error = '%s', errno = %d\n", strerror(e), e);
+ "ERROR: error = '%s', errno = %d\n", strerror(errno), errno);
return 1;
}
printf("superblock: bytenr=%llu, device=%s\n", sb_bytenr, filename);
@@ -186,11 +184,14 @@ static void print_sys_chunk_array(struct btrfs_super_block *sb)
struct extent_buffer *buf;
struct btrfs_disk_key *disk_key;
struct btrfs_chunk *chunk;
- struct btrfs_key key;
- u8 *ptr, *array_end;
+ u8 *array_ptr;
+ unsigned long sb_array_offset;
u32 num_stripes;
+ u32 array_size;
u32 len = 0;
- int i = 0;
+ u32 cur_offset;
+ struct btrfs_key key;
+ int item;
buf = malloc(sizeof(*buf) + sizeof(*sb));
if (!buf) {
@@ -198,34 +199,70 @@ static void print_sys_chunk_array(struct btrfs_super_block *sb)
exit(1);
}
write_extent_buffer(buf, sb, 0, sizeof(*sb));
- ptr = sb->sys_chunk_array;
- array_end = ptr + btrfs_super_sys_array_size(sb);
+ array_size = btrfs_super_sys_array_size(sb);
+
+ array_ptr = sb->sys_chunk_array;
+ sb_array_offset = offsetof(struct btrfs_super_block, sys_chunk_array);
+ cur_offset = 0;
+ item = 0;
+
+ while (cur_offset < array_size) {
+ disk_key = (struct btrfs_disk_key *)array_ptr;
+ len = sizeof(*disk_key);
+ if (cur_offset + len > array_size)
+ goto out_short_read;
- while (ptr < array_end) {
- disk_key = (struct btrfs_disk_key *)ptr;
btrfs_disk_key_to_cpu(&key, disk_key);
- printf("\titem %d ", i);
- btrfs_print_key(disk_key);
+ array_ptr += len;
+ sb_array_offset += len;
+ cur_offset += len;
- len = sizeof(*disk_key);
+ printf("\titem %d ", item);
+ btrfs_print_key(disk_key);
putchar('\n');
- ptr += len;
if (key.type == BTRFS_CHUNK_ITEM_KEY) {
- chunk = (struct btrfs_chunk *)(ptr - (u8 *)sb);
+ chunk = (struct btrfs_chunk *)sb_array_offset;
+ /*
+ * At least one btrfs_chunk with one stripe must be
+ * present, exact stripe count check comes afterwards
+ */
+ len = btrfs_chunk_item_size(1);
+ if (cur_offset + len > array_size)
+ goto out_short_read;
+
print_chunk(buf, chunk);
num_stripes = btrfs_chunk_num_stripes(buf, chunk);
+ if (!num_stripes) {
+ printk(
+ "ERROR: invalid number of stripes %u in sys_array at offset %u\n",
+ num_stripes, cur_offset);
+ break;
+ }
len = btrfs_chunk_item_size(num_stripes);
+ if (cur_offset + len > array_size)
+ goto out_short_read;
} else {
- BUG();
+ printk(
+ "ERROR: unexpected item type %u in sys_array at offset %u\n",
+ (u32)key.type, cur_offset);
+ break;
}
+ array_ptr += len;
+ sb_array_offset += len;
+ cur_offset += len;
- ptr += len;
- i++;
+ item++;
}
free(buf);
+ return;
+
+out_short_read:
+ printk("ERROR: sys_array too short to read %u bytes at offset %u\n",
+ len, cur_offset);
+ free(buf);
}
static int empty_backup(struct btrfs_root_backup *backup)
@@ -295,7 +332,7 @@ struct readable_flag_entry {
#define DEF_INCOMPAT_FLAG_ENTRY(bit_name) \
{BTRFS_FEATURE_INCOMPAT_##bit_name, #bit_name}
-struct readable_flag_entry incompat_flags_array[] = {
+static struct readable_flag_entry incompat_flags_array[] = {
DEF_INCOMPAT_FLAG_ENTRY(MIXED_BACKREF),
DEF_INCOMPAT_FLAG_ENTRY(DEFAULT_SUBVOL),
DEF_INCOMPAT_FLAG_ENTRY(MIXED_GROUPS),
@@ -315,7 +352,7 @@ static const int incompat_flags_num = sizeof(incompat_flags_array) /
#define DEF_SUPER_FLAG_ENTRY(bit_name) \
{BTRFS_SUPER_FLAG_##bit_name, #bit_name}
-struct readable_flag_entry super_flags_array[] = {
+static struct readable_flag_entry super_flags_array[] = {
DEF_HEADER_FLAG_ENTRY(WRITTEN),
DEF_HEADER_FLAG_ENTRY(RELOC),
DEF_SUPER_FLAG_ENTRY(CHANGING_FSID),