summaryrefslogtreecommitdiffstats
path: root/libblkid/befs.c
diff options
context:
space:
mode:
Diffstat (limited to 'libblkid/befs.c')
-rw-r--r--libblkid/befs.c480
1 files changed, 0 insertions, 480 deletions
diff --git a/libblkid/befs.c b/libblkid/befs.c
deleted file mode 100644
index 847860ad5..000000000
--- a/libblkid/befs.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (C) 2010 Jeroen Oortwijn <oortwijn@gmail.com>
- *
- * Partly based on the Haiku BFS driver by
- * Axel Dörfler <axeld@pinc-software.de>
- *
- * Also inspired by the Linux BeFS driver by
- * Will Dyson <will_dyson@pobox.com>, et al.
- *
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <inttypes.h>
-#include <byteswap.h>
-#include "bitops.h"
-#include "superblocks.h"
-
-#define B_OS_NAME_LENGTH 0x20
-#define SUPER_BLOCK_MAGIC1 0x42465331 /* BFS1 */
-#define SUPER_BLOCK_MAGIC2 0xdd121031
-#define SUPER_BLOCK_MAGIC3 0x15b6830e
-#define SUPER_BLOCK_FS_ENDIAN 0x42494745 /* BIGE */
-#define INODE_MAGIC1 0x3bbe0ad9
-#define BPLUSTREE_MAGIC 0x69f6c2e8
-#define BPLUSTREE_NULL -1LL
-#define NUM_DIRECT_BLOCKS 12
-#define B_UINT64_TYPE 0x554c4c47 /* ULLG */
-#define KEY_NAME "be:volume_id"
-#define KEY_SIZE 8
-#define FS16_TO_CPU(value, fs_is_le) (fs_is_le ? le16_to_cpu(value) \
- : be16_to_cpu(value))
-#define FS32_TO_CPU(value, fs_is_le) (fs_is_le ? le32_to_cpu(value) \
- : be32_to_cpu(value))
-#define FS64_TO_CPU(value, fs_is_le) (fs_is_le ? le64_to_cpu(value) \
- : be64_to_cpu(value))
-
-typedef struct block_run {
- int32_t allocation_group;
- uint16_t start;
- uint16_t len;
-} __attribute__((packed)) block_run, inode_addr;
-
-struct befs_super_block {
- char name[B_OS_NAME_LENGTH];
- int32_t magic1;
- int32_t fs_byte_order;
- uint32_t block_size;
- uint32_t block_shift;
- int64_t num_blocks;
- int64_t used_blocks;
- int32_t inode_size;
- int32_t magic2;
- int32_t blocks_per_ag;
- int32_t ag_shift;
- int32_t num_ags;
- int32_t flags;
- block_run log_blocks;
- int64_t log_start;
- int64_t log_end;
- int32_t magic3;
- inode_addr root_dir;
- inode_addr indices;
- int32_t pad[8];
-} __attribute__((packed));
-
-typedef struct data_stream {
- block_run direct[NUM_DIRECT_BLOCKS];
- int64_t max_direct_range;
- block_run indirect;
- int64_t max_indirect_range;
- block_run double_indirect;
- int64_t max_double_indirect_range;
- int64_t size;
-} __attribute__((packed)) data_stream;
-
-struct befs_inode {
- int32_t magic1;
- inode_addr inode_num;
- int32_t uid;
- int32_t gid;
- int32_t mode;
- int32_t flags;
- int64_t create_time;
- int64_t last_modified_time;
- inode_addr parent;
- inode_addr attributes;
- uint32_t type;
- int32_t inode_size;
- uint32_t etc;
- data_stream data;
- int32_t pad[4];
- int32_t small_data[0];
-} __attribute__((packed));
-
-struct small_data {
- uint32_t type;
- uint16_t name_size;
- uint16_t data_size;
- char name[0];
-} __attribute__((packed));
-
-struct bplustree_header {
- uint32_t magic;
- uint32_t node_size;
- uint32_t max_number_of_levels;
- uint32_t data_type;
- int64_t root_node_pointer;
- int64_t free_node_pointer;
- int64_t maximum_size;
-} __attribute__((packed));
-
-struct bplustree_node {
- int64_t left_link;
- int64_t right_link;
- int64_t overflow_link;
- uint16_t all_key_count;
- uint16_t all_key_length;
- char name[0];
-} __attribute__((packed));
-
-static unsigned char *get_block_run(blkid_probe pr, const struct befs_super_block *bs,
- const struct block_run *br, int fs_le)
-{
- return blkid_probe_get_buffer(pr,
- ((blkid_loff_t) FS32_TO_CPU(br->allocation_group, fs_le)
- << FS32_TO_CPU(bs->ag_shift, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le))
- + ((blkid_loff_t) FS16_TO_CPU(br->start, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le)),
- (blkid_loff_t) FS16_TO_CPU(br->len, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le));
-}
-
-static unsigned char *get_custom_block_run(blkid_probe pr,
- const struct befs_super_block *bs,
- const struct block_run *br,
- int64_t offset, uint32_t length, int fs_le)
-{
- if (offset + length > (int64_t) FS16_TO_CPU(br->len, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le))
- return NULL;
-
- return blkid_probe_get_buffer(pr,
- ((blkid_loff_t) FS32_TO_CPU(br->allocation_group, fs_le)
- << FS32_TO_CPU(bs->ag_shift, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le))
- + ((blkid_loff_t) FS16_TO_CPU(br->start, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le))
- + offset,
- length);
-}
-
-static unsigned char *get_tree_node(blkid_probe pr, const struct befs_super_block *bs,
- const struct data_stream *ds,
- int64_t start, uint32_t length, int fs_le)
-{
- if (start < (int64_t) FS64_TO_CPU(ds->max_direct_range, fs_le)) {
- int64_t br_len;
- size_t i;
-
- for (i = 0; i < NUM_DIRECT_BLOCKS; i++) {
- br_len = (int64_t) FS16_TO_CPU(ds->direct[i].len, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le);
- if (start < br_len)
- return get_custom_block_run(pr, bs,
- &ds->direct[i],
- start, length, fs_le);
- else
- start -= br_len;
- }
- } else if (start < (int64_t) FS64_TO_CPU(ds->max_indirect_range, fs_le)) {
- struct block_run *br;
- int64_t max_br, br_len, i;
-
- start -= FS64_TO_CPU(ds->max_direct_range, fs_le);
- max_br = ((int64_t) FS16_TO_CPU(ds->indirect.len, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le))
- / sizeof(struct block_run);
-
- br = (struct block_run *) get_block_run(pr, bs, &ds->indirect,
- fs_le);
- if (!br)
- return NULL;
-
- for (i = 0; i < max_br; i++) {
- br_len = (int64_t) FS16_TO_CPU(br[i].len, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le);
- if (start < br_len)
- return get_custom_block_run(pr, bs, &br[i],
- start, length, fs_le);
- else
- start -= br_len;
- }
- } else if (start < (int64_t) FS64_TO_CPU(ds->max_double_indirect_range, fs_le)) {
- struct block_run *br;
- int64_t di_br_size, br_per_di_br, di_index, i_index;
-
- start -= (int64_t) FS64_TO_CPU(ds->max_indirect_range, fs_le);
-
- di_br_size = (int64_t) FS16_TO_CPU(ds->double_indirect.len,
- fs_le) << FS32_TO_CPU(bs->block_shift, fs_le);
- if (di_br_size == 0)
- return NULL;
-
- br_per_di_br = di_br_size / sizeof(struct block_run);
- if (br_per_di_br == 0)
- return NULL;
-
- di_index = start / (br_per_di_br * di_br_size);
- i_index = (start % (br_per_di_br * di_br_size)) / di_br_size;
- start = (start % (br_per_di_br * di_br_size)) % di_br_size;
-
- br = (struct block_run *) get_block_run(pr, bs,
- &ds->double_indirect, fs_le);
- if (!br)
- return NULL;
-
- br = (struct block_run *) get_block_run(pr, bs, &br[di_index],
- fs_le);
- if (!br)
- return NULL;
-
- return get_custom_block_run(pr, bs, &br[i_index], start, length,
- fs_le);
- }
- return NULL;
-}
-
-static int32_t compare_keys(const char keys1[], uint16_t keylengths1[], int32_t index,
- const char *key2, uint16_t keylength2, int fs_le)
-{
- const char *key1;
- uint16_t keylength1;
- int32_t result;
-
- key1 = &keys1[index == 0 ? 0 : FS16_TO_CPU(keylengths1[index - 1],
- fs_le)];
- keylength1 = FS16_TO_CPU(keylengths1[index], fs_le)
- - (index == 0 ? 0 : FS16_TO_CPU(keylengths1[index - 1],
- fs_le));
-
- result = strncmp(key1, key2, min(keylength1, keylength2));
-
- if (result == 0)
- return keylength1 - keylength2;
-
- return result;
-}
-
-static int64_t get_key_value(blkid_probe pr, const struct befs_super_block *bs,
- const struct befs_inode *bi, const char *key, int fs_le)
-{
- struct bplustree_header *bh;
- struct bplustree_node *bn;
- uint16_t *keylengths;
- int64_t *values;
- int64_t node_pointer;
- int32_t first, last, mid, cmp;
-
- bh = (struct bplustree_header *) get_tree_node(pr, bs, &bi->data, 0,
- sizeof(struct bplustree_header), fs_le);
- if (!bh)
- return -1;
-
- if ((int32_t) FS32_TO_CPU(bh->magic, fs_le) != BPLUSTREE_MAGIC)
- return -1;
-
- node_pointer = FS64_TO_CPU(bh->root_node_pointer, fs_le);
-
- do {
- bn = (struct bplustree_node *) get_tree_node(pr, bs, &bi->data,
- node_pointer, FS32_TO_CPU(bh->node_size, fs_le), fs_le);
- if (!bn)
- return -1;
-
- keylengths = (uint16_t *) ((uint8_t *) bn
- + ((sizeof(struct bplustree_node)
- + FS16_TO_CPU(bn->all_key_length, fs_le)
- + sizeof(int64_t) - 1)
- & ~(sizeof(int64_t) - 1)));
- values = (int64_t *) ((uint8_t *) keylengths
- + FS16_TO_CPU(bn->all_key_count, fs_le)
- * sizeof(uint16_t));
- first = 0;
- mid = 0;
- last = FS16_TO_CPU(bn->all_key_count, fs_le) - 1;
-
- cmp = compare_keys(bn->name, keylengths, last, key, strlen(key),
- fs_le);
- if (cmp == 0) {
- if ((int64_t) FS64_TO_CPU(bn->overflow_link, fs_le)
- == BPLUSTREE_NULL)
- return FS64_TO_CPU(values[last], fs_le);
- else
- node_pointer = FS64_TO_CPU(values[last], fs_le);
- } else if (cmp < 0)
- node_pointer = FS64_TO_CPU(bn->overflow_link, fs_le);
- else {
- while (first <= last) {
- mid = (first + last) / 2;
-
- cmp = compare_keys(bn->name, keylengths, mid,
- key, strlen(key), fs_le);
- if (cmp == 0) {
- if ((int64_t) FS64_TO_CPU(bn->overflow_link,
- fs_le) == BPLUSTREE_NULL)
- return FS64_TO_CPU(values[mid],
- fs_le);
- else
- break;
- } else if (cmp < 0)
- first = mid + 1;
- else
- last = mid - 1;
- }
- if (cmp < 0)
- node_pointer = FS64_TO_CPU(values[mid + 1],
- fs_le);
- else
- node_pointer = FS64_TO_CPU(values[mid], fs_le);
- }
- } while ((int64_t) FS64_TO_CPU(bn->overflow_link, fs_le)
- != BPLUSTREE_NULL);
- return 0;
-}
-
-static int get_uuid(blkid_probe pr, const struct befs_super_block *bs,
- uint64_t * const uuid, int fs_le)
-{
- struct befs_inode *bi;
- struct small_data *sd;
-
- bi = (struct befs_inode *) get_block_run(pr, bs, &bs->root_dir, fs_le);
- if (!bi)
- return -1;
-
- if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
- return -1;
-
- sd = (struct small_data *) bi->small_data;
-
- do {
- if (FS32_TO_CPU(sd->type, fs_le) == B_UINT64_TYPE
- && FS16_TO_CPU(sd->name_size, fs_le) == strlen(KEY_NAME)
- && FS16_TO_CPU(sd->data_size, fs_le) == KEY_SIZE
- && strcmp(sd->name, KEY_NAME) == 0) {
-
- memcpy(uuid,
- sd->name + FS16_TO_CPU(sd->name_size, fs_le) + 3,
- sizeof(uint64_t));
-
- break;
- } else if (FS32_TO_CPU(sd->type, fs_le) == 0
- && FS16_TO_CPU(sd->name_size, fs_le) == 0
- && FS16_TO_CPU(sd->data_size, fs_le) == 0)
- break;
-
- sd = (struct small_data *) ((uint8_t *) sd
- + sizeof(struct small_data)
- + FS16_TO_CPU(sd->name_size, fs_le) + 3
- + FS16_TO_CPU(sd->data_size, fs_le) + 1);
-
- } while ((intptr_t) sd < (intptr_t) bi
- + (int32_t) FS32_TO_CPU(bi->inode_size, fs_le)
- - (int32_t) sizeof(struct small_data));
- if (*uuid == 0
- && (FS32_TO_CPU(bi->attributes.allocation_group, fs_le) != 0
- || FS16_TO_CPU(bi->attributes.start, fs_le) != 0
- || FS16_TO_CPU(bi->attributes.len, fs_le) != 0)) {
- int64_t value;
-
- bi = (struct befs_inode *) get_block_run(pr, bs,
- &bi->attributes, fs_le);
- if (!bi)
- return -1;
-
- if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
- return -1;
-
- value = get_key_value(pr, bs, bi, KEY_NAME, fs_le);
-
- if (value < 0)
- return value;
- else if (value > 0) {
- bi = (struct befs_inode *) blkid_probe_get_buffer(pr,
- value << FS32_TO_CPU(bs->block_shift, fs_le),
- FS32_TO_CPU(bs->block_size, fs_le));
- if (!bi)
- return -1;
-
- if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
- return -1;
-
- if (FS32_TO_CPU(bi->type, fs_le) == B_UINT64_TYPE
- && FS64_TO_CPU(bi->data.size, fs_le) == KEY_SIZE
- && FS16_TO_CPU(bi->data.direct[0].len, fs_le)
- == 1) {
- uint64_t *attr_data;
-
- attr_data = (uint64_t *) get_block_run(pr, bs,
- &bi->data.direct[0], fs_le);
- if (!attr_data)
- return -1;
-
- *uuid = *attr_data;
- }
- }
- }
- return 0;
-}
-
-static int probe_befs(blkid_probe pr, const struct blkid_idmag *mag)
-{
- struct befs_super_block *bs;
- const char *version = NULL;
- uint64_t volume_id = 0;
- int fs_le, ret;
-
- bs = (struct befs_super_block *) blkid_probe_get_buffer(pr,
- mag->sboff - B_OS_NAME_LENGTH,
- sizeof(struct befs_super_block));
- if (!bs)
- return -1;
-
- if (le32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1
- && le32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2
- && le32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3
- && le32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) {
- fs_le = 1;
- version = "little-endian";
- } else if (be32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1
- && be32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2
- && be32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3
- && be32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) {
- fs_le = 0;
- version = "big-endian";
- } else
- return -1;
-
- ret = get_uuid(pr, bs, &volume_id, fs_le);
-
- if (ret < 0)
- return ret;
-
- /*
- * all checks pass, set LABEL, VERSION and UUID
- */
- if (strlen(bs->name))
- blkid_probe_set_label(pr, (unsigned char *) bs->name,
- sizeof(bs->name));
- if (version)
- blkid_probe_set_version(pr, version);
-
- if (volume_id)
- blkid_probe_sprintf_uuid(pr, (unsigned char *) &volume_id,
- sizeof(volume_id), "%016" PRIx64,
- FS64_TO_CPU(volume_id, fs_le));
- return 0;
-}
-
-const struct blkid_idinfo befs_idinfo =
-{
- .name = "befs",
- .usage = BLKID_USAGE_FILESYSTEM,
- .probefunc = probe_befs,
- .minsz = 1024 * 1440,
- .magics = {
- { .magic = "BFS1", .len = 4, .sboff = B_OS_NAME_LENGTH },
- { .magic = "1SFB", .len = 4, .sboff = B_OS_NAME_LENGTH },
- { .magic = "BFS1", .len = 4, .sboff = 0x200 +
- B_OS_NAME_LENGTH },
- { .magic = "1SFB", .len = 4, .sboff = 0x200 +
- B_OS_NAME_LENGTH },
- { NULL }
- }
-};